Krótkie pytanie o foreach


(Nowypunktwidzenia) #1

Hej,

mam pytanie - dlaczego nie działa coś takiego :

foreach (TextBox kontrolka in pojemnik.Children){

            }

Środek jest nieważny - wywala przy włączeniu programu, mój pojemnik to zwykły Grid w WPF.

Błąd, który wyrzuca to Unable to cast object of type 'System.Windows.Controls.Label' to type 'System.Windows.Controls.TextBox'.

Dlaczego on bierze labelki, skoro w foreach zaznaczyłem, że chodzi mi wyłącznie o elementy TextBox - jak to naprawić, chciałbym skasować zawartość wszystkich textboxów.


(Grzelix) #2

nie bierzesz textbox'ów tylko childrens pojemnika - wszystkie jakie ma.

poprawnić to możesz coś w stylu:

foreach (System.Windows.Controls kontrolka in pojemnik.Children){

if(kontrolka.type == textbox)

    //do something

            }

powyższy kod jest jedynie szkicem.


(Somekindsoftware) #3

W którym momencie? W pętli idziesz po wszystkich "dzieciach" pojemnika i każdy z nich próbujesz rzutować na TextBox. Tam nie ma żadnej filtracji.

Albo z operatorem is i rzutowaniem:

foreach (var kontrolka in pojemnik.Children)

{

    if (kontrolka is TextBox)

    {

        ((TextBox)kontrolka).Text = "AAA";

    }

}

Albo z operatorem as:

foreach (var kontrolka in pojemnik.Children)

{

    TextBox txt = kontrolka as TextBox;

    if (txt != null)

    {

        txt.Text = "AAA";

    }

}

A najprościej jak zwykle użyć LINQ:

foreach (var kontrolka in pojemnik.Children.OfType())

{

    kontrolka.Text = "AAA";

}

I tutaj faktycznie operujemy na wyselekcjonowanej kolekcji TextBoxów.


(Nowypunktwidzenia) #4

Dzięki :slight_smile:

A mógłby mi ktoś jeszcze wyjaśnić czym różni się kod zdarzenia :

void button1_Click(object sender, RoutedEventArgs e)

        {

            Button przycisk = e.Source as Button;

            przycisk.Content = "tresc";

        }

od

void button1_Click(object sender, RoutedEventArgs e)

        {

            Button przycisk = (Button) sender;

            przycisk.Content = "tresc";

        }

Oba działają i trochę mnie dziwi, że są aż dwa sposoby - pewnie jedno z nich jest używane w innych przypadkach, prosiłbym o krótkie wyjaśnienie (co przy pomocy którego mogę zrobić).


(litestep) #5

Różnią się zachowaniem w przypadku kiedy podepniesz tego handlera do czegoś innego niż Button: pierwsze rzuci NullPointerException* w drugiej linijce a drugi przykład rzuci ClassCastException* w pierwszej linijce. Czyli powinieneś albo sprawdzać czy wynik z "as" nie jest nullem, jak robi @somekind wyżej albo sprawdzać jakiej klasy jest obiekt przed jego rzutowaniem.

* nie mam pojęcia jak się te błędy w .Net nazywają :slight_smile: