Weryfikacja i ustawianie właściwości textBox i checkBox

0

Witam,
poproszę o podpowiedź jak zrealizować poniższą funkcjonalność.
Na formularzu (Windows Form) mam umieszczonych kilka par kontrolek checkBox i textBox (dla uproszczenia opisywać będę tylko dwie pary) czyli:
checkBox1 i odpowiadający mu textBox1
checkBox2 i odpowiadający mu textBox2
Dla każdej z par w momencie zaznaczania checkBox'a ustawiam Fokus na odpowiadający mu textBox.
Funkcjonalność na której mi zależy, to nie dopuścić by na formularzu znajdowała się para: zaznaczony checkBox i odpowiadający jemu textBox bez fokusa (kursora) i bez wprowadzonego tekstu.
Realizuję to poprzez wykorzystanie zdarzenie textBox_Validating. W zdarzeniu tym sprawdzam, czy długość tekstu w textBox jest równa 0. Jeśli tak to ustawiam checkBox.Checked na 'false' (czyli w momencie opuszczania textBoxa, jeśli nie ma w nim tekstu, odznaczam checkBox) np.:

  1. Klikam w niezaznaczony chkBox1 (zaznaczam go). W zdarzeniu checkBox.CheckedChanged ustawiam fokus na textBox (textBox1.Fokus()).
  2. textBox1 otrzymuje fokus czyli pojawia się w nim kursor do wprwadzania tekstu, ale TextBox1 jest "pusty" - nie ma jeszcze wprowadzonego tekstu.
  3. Jeśli teraz kliknę w checkBox2, jako pierwsze, wywołane jest zdarzenie TextBox1_Validating w którym sprawdzam, że ChekBox1.Checked jest true i ponieważ textBox1.text.Lengt==0, to ustawiam checkBox1.Checked na false. Wszystko jest OK.
    Problem zaczyna się jeśli jestem w sytuacji opisanej w punkcie 2. i
  4. Jeśli teraz kliknę nie w checkBox2, a w checkBox1 (czyli chcę "odznaczyć" checkBox1), to "odznaczenie" to nie przynosi efektów - checkBox1 cały czas jest zaznaczony
    Poniżej kod dwóch method obsługujących zdarzenia.
        private void checkBox1_CheckedChanged(object sender, EventArgs e) {
            if (((CheckBox1)sender).Checked) {
                textBox1.Focus();
            }
            else {
                textBox1.Text = "";
            }
        }

        private void textBox1_Validating(object sender,CancelEventArgs e) {
                if ((sender as TextBox1).TextLength == 0) {
                    checkBox1.Checked = false;
                }
        }

Czy jest jakiś sposób (być może inne rozwiązanie) by zrealizować powyższą funkcjonalność?
Wszystkie deklaracje metod obsługi zdarzeń są wygenerowane przez VisualStudio

0

Jest. Normalny sposób :)

Rozwiązania masz przynajmniej dwa:

  1. Moim zdaniem lepsze - wykorzystaj UserControl. To coś w rodzaju własnego komponentu, ale nie do końca. Tworzysz nowy UserControl i na początek widzisz jakby panel, na którym kładziesz sobie kontrolki. Wszystko możesz oprogramować tak, jak chcesz, np:
void checkBox_CheckedChanged(...)
{
   textBox.Focus();
}

Tworzysz sobie jakąś publiczną metodę Validate, w której po prostu sprawdzasz:

if(string.NullOrEmpty(textBox.Text.Length))
  checkBox.Checked = false;

Potem na swojej formie kładziesz kilka tych kontrolek, ile potrzebujesz. A na koniec musisz tylko wywołać validate. Robisz to oczywiście w pętli.

  1. Zdecydowanie gorszy sposób:
    Do każdego checkBoxa przypisujesz we właściwości TAG odpowiadający mu textBox.
    Każdy checkBox ma to samo zdarzenie checkedChanged:
CheckBox cb = sender as CheckBox;
if(cb != null && cb.Checked)
{
  TextBox tb = cb.Tag as TextBox;
  if(tb != null)
    tb.Focus();
}

Trudniej będzie w drugą stronę. TextBoxy też powinny mieć w tagu odpowiadającego CheckBoxa. Dlatego najlepiej to zrobić za pomocą UserControl.

0

Dziękuję za podpowiedź.
Zacząłem próby z UserControl i na razie po jego utworzeniu, pojawia mi się błąd w momencie kiedy wstawiam go na moją Formę (zakładam, że może jakoś sobie z tym poradzę). Jednak mam jeszcze inną wątpliwość. Jeśli dobrze zrozumiałem Twój opis wariantu "lepszego" kontrolka UserControl posłużyć ma do "sparowania" checkBox'a i textBox'a, natomiast metoda Validate ma posłużyć do sprawdzenia nieprawidłowych wartości (pusty textBoch przy "zahaczonym" checkBox'ie) uruchamiana np przed pobraniem wartości z pól. Wydaje mi się, że takie rozwiązanie nie daje możliwości weryfikacji złych ustawień dynamicznie - tzn podczas opuszczania textBoxa (być może nieprecyzyjnie napisałem, ale o taką funkcjonalność mi chodzi). Jeśli się mylę to poproszę o dodatkowe wskazówki, jeśli nie to może jakiś kolejny sposób.

0

Jeśli chcesz podczas opuszczania textboxa, to przecież możesz to oprogramować na poziomie usercontrol :| Potraktuj user control tak, jakby było osobną formą, na którą kładziesz komponenty. A potem możesz na innej formie położyć mnóstwo tych user control. I wszystko stanie się jasne.

0

Tylko problem w tym oprogramowaniu :). Wydaje mi się, że problem ten pojawi się niezależnie czy kontrolki będą bezpośrednio na formularzu, czy w UserControl (jak sam piszesz UserControl jest jakby niezależnym formularzem).
A może spróbujmy znaleźć rozwiązanie patrząc z innej strony.
Mam tylko dwie kotrolki: Textbox1 i CheckBox1. Chekbox1 ma status Checked, natomiast fokus ustawiony jest na Textbox1.
I teraz klikam myszką w ChekBox1 tak by go odznaczyć. Z tego co mi się udało zorientować najpierw pojawiają się zdarzenia związane z utratą fokusa w TextBox1 (Validating, Validated, Leave), a dopiero później związane z CheckBox1 (CheckedChange i Click). W związku z tym, jeśli opuszczając TextBox1 zmieniam stan na "uncheked" i dopiero potem pojawia się obsługa klikniętego CheckBox1, to zamiast odznaczenia, zostaje on ponownie zaznaczony.
I teraz pytanie: W jaki sposób obsługując zdarzenie wyjścia z TextBox1 (np Leave) można sprawdzić, kliknięcie której kontrolki, spowodowało utratę fokusa przez TextBox1. Czytałem że są kolejki zdarzeń i komunikatów (w których zapewne czekają na obsługę zdarzenia związane z CheckBox1 - po zakończeniu zdarzeń TextBox'a), ale jak się do nich "dobrać"? (Niestety obiekt sender przesłany jako argument, w metodzie obsługującej zdarzenie Leave, wskazuje na TextBox1).

0

Czekaj, od samego początku masz jakieś błędne założenie. Teraz się wczytałem:

Funkcjonalność na której mi zależy, to nie dopuścić by na formularzu znajdowała się para: zaznaczony checkBox i odpowiadający jemu textBox bez fokusa (kursora) i bez wprowadzonego tekstu.

Z tego wynika, że chcesz mieć taką sytuację, w której każdy zaznaczony checkbox będzie miał textbox z focusem? Tylko jedna kontrolka może mieć focus w danym momencie.

Co konkretnie chcesz osiągnąć?

0

Kurczę, wczytałeś się w pierwszy post i faktycznie tam nie jest precyzyjny opis.
Spróbuję jeszcze raz (załączam plik z przykładowym formularzem).
Założenie jest takie: jeśli checkbox nie jest zaznaczony to textbox po prawej stronie checkboxa'a nie jest aktywny (enable=false), natomiast jeśli chckbox jest zaznaczony to odpowiadający mu textbox jest aktywny, ale nie może być pusty (jedyny wyjątek to moment kliknięcia w checkboxa i przeniesienia focusa do pustego textboxa)).
Przykład (z załączonego pliku) pokazuje stan tuż po kliknięciu w checkbox2. Checkbox2 został zaznaczony, a zmiana statusu checkboxa2 spowodowała przeniesienie fokus'a do sąsiadującego textbox'a. Teraz mogę:1) wpisać coś do textboxa i z niego wyjść lub 2) wyjść z textboxa nic nie wpisując. Skupmy się na przypadku 2). Załóżmy (na razie), że wyjście z textboxa realizujemy przy pomocy myszki (a nie klawiatury) klikając w jedną z pozostałych aktywnych kontrolek. Wychodząc z textboxa, chcę sprawdzić czy został wpisany jakiś text. Jeśli nie ma, to muszę zdjąć (programowo) zaznaczenie z checkboxa2 (tak aby nie było sytuacji, że jest zaznaczony chackbox a textbox jest pusty).
I to właściwie wszystko.
Wszystko jest OK, gdy wyjście z textboxa jest spowodowane kliknięciem w dowolną aktywną kontrolkę poza checkbox2. Natomiast klikniecie w zaznaczony checkbox2 nie powoduje zdjęcia zaznaczenia (chociaż mrugniecie checkboxa wskazuje na to, że zaznaczenie jest (programowo) zdjęte, ale zaraz potem jest realizowane kliknięcie w checkbox (tyle że jest on już programów odznaczony i de facto klikniecie zamiast go odznaczyć - zaznacza go ponownie). Dlatego program powinien wiedzieć (opuszczając textbox), w którą kontrolkę nastąpiło klikniecie. Wtedy realizowałbym odznaczenie tylko wtedy jeśli nie kliknięto checkbox2, a jeśli kliknięto, to odznaczenia programowego nie przeprowadzałbym (odznaczenie checkbox2, nastąpi poprzez jego klikniecie).
Nie wiem czy coś Ci rozjaśniłem ?

0

Teraz już wiem o co Ci chodzi. CheckBox jest odznaczany, ale natychmiast następuje jego zaznaczenie. Nie mogę wymyślić nic sensownego, bo zawsze jest jakiś problem. Ale pokombinowałbym z:
CheckBox.AutoCheck
CheckBox.Validating
CheckBox.CheckStateChanged

0 użytkowników online, w tym zalogowanych: 0, gości: 0