W programie desktopowym stworzono rozwijaną listę oraz przypisano cztery funkcje do obsługi zdarzeń tej kontrolki. Jaki komunikat pojawi się po dokonaniu wyboru w tej liście?
W XAML (uproszczona wersja): <ComboBox SelectionChanged="Funkcja1" DragEnter="Funkcja2"
LostFocus="Funkcja3" KeyDown="Funkcja4">
</ComboBox>
W kodzie: private void Funkcja1(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("Zdarzenie 1");
}
private void Funkcja2(object sender, DragEventArgs e)
{
MessageBox.Show("Zdarzenie 2");
}
private void Funkcja3(object sender, RoutedEventArgs e)
{
MessageBox.Show("Zdarzenie 3");
}
private void Funkcja4(object sender, KeyEventArgs e)
{
MessageBox.Show("Zdarzenie 4");
}
Wybrałeś dokładnie to, co trzeba. W tej sytuacji kluczowe jest rozpoznanie, że zdarzenie SelectionChanged jest wywoływane zawsze wtedy, gdy użytkownik wybierze inną pozycję z ComboBoxa. I to właśnie do tego zdarzenia przypisana jest metoda Funkcja1, która wyświetla komunikat "Zdarzenie 1". Trochę to wygląda niepozornie, ale SelectionChanged to jeden z najczęściej obsługiwanych eventów w aplikacjach desktopowych opartych na WPF czy UWP – praktycznie zawsze reagujemy na wybór użytkownika w kontrolkach ComboBox, ListBox albo nawet ListView. Z mojego doświadczenia wynika, że początkujący programiści często mylą to zdarzenie z innymi, jak LostFocus, które odpala się, gdy kontrolka traci fokus, albo z DragEnter (zupełnie inny przypadek, bo dotyczy przeciągania danych). Warto pamiętać, że KeyDown reaguje dopiero na naciśnięcie klawisza, a nie na wybór myszką. Takie rozróżnienie jest codziennością przy tworzeniu bardziej zaawansowanych interfejsów użytkownika. Praktyczna wskazówka: jeśli chcesz reagować na wybór użytkownika i np. ładować dodatkowe dane czy weryfikować coś po stronie aplikacji, to SelectionChanged jest strzałem w dziesiątkę. Standardy branżowe sugerują nie przesadzać z obsługą zbyt wielu eventów jednocześnie dla tej samej kontrolki, bo to może prowadzić do konfliktów i dziwnych zachowań UI. Mocno polecam samemu poeksperymentować – otworzyć Visual Studio, zrobić prostą aplikację WPF, podpiąć te eventy i zobaczyć, które kiedy się odpalają. Dzięki temu dużo szybciej utrwala się ta wiedza niż z samej teorii.
W zadaniu chodziło o to, jakie zdarzenie zostanie wywołane po dokonaniu wyboru w rozwijanej liście ComboBox. Wielu osobom może się wydawać, że zmiana wyboru w kontrolce może powodować aktywację różnych zdarzeń, takich jak LostFocus czy KeyDown, zwłaszcza jeśli wcześniej mieli styczność z WinForms lub innymi frameworkami UI. Zdarzenie LostFocus jednak zostaje wywołane tylko wtedy, gdy kontrolka traci fokus, czyli gdy użytkownik przestaje ją aktywnie obsługiwać, na przykład klikając gdzie indziej – nie podczas zwykłego wyboru elementu. KeyDown natomiast obsługuje sytuacje, w których użytkownik naciska klawisz na klawiaturze, więc ma to sens tylko, gdy wybór w ComboBox jest dokonywany za pomocą klawiatury, ale nawet wtedy domyślnie KeyDown nie informuje o zmianie wybranego elementu, tylko o naciśnięciu klawisza. DragEnter jest całkiem osobną kategorią – to zdarzenie wywołuje się tylko wtedy, gdy przeciągamy jakiś element nad ComboBoxem, co w praktyce nie ma nic wspólnego z normalnym wyborem z listy. Często spotykam się z przekonaniem, że Focus i jego utrata mają coś wspólnego z wyborem wartości, ale według dokumentacji Microsoftu oraz praktyki programistycznej to dwie różne sprawy. SelectionChanged to standardowy, branżowy sposób wykrywania zmiany wyboru w kontrolkach typu ComboBox – niezależnie od tego czy użytkownik używa myszki, klawiatury czy nawet ekranów dotykowych. Właśnie dlatego ta odpowiedź jest właściwa. Moim zdaniem nieporozumienia biorą się często z niejasnego rozumienia różnicy między różnymi zdarzeniami UI. W środowiskach takich jak WPF lub UWP bardzo się to rozdziela i dokumentacja zawsze to podkreśla. Dobrą praktyką jest przypisywanie każdej funkcji tylko do tych zdarzeń, które rzeczywiście dotyczą konkretnej akcji użytkownika – to pozwala uniknąć nieprzyjemnych bugów i nieoczekiwanych komunikatów w aplikacji.