Czy w WPF istnieje zdarzenie, którego można użyć do określenia, kiedy TabControl
zmienia się wybrana karta?
Próbowałem używać, TabControl.SelectionChanged
ale jest wielokrotnie uruchamiany, gdy zmienia się wybór dziecka w zakładce.
wpf
events
tabcontrol
Jon Kragh
źródło
źródło
sender
zamiaste.Source
e.Handled = true
aby zapobiec bulgotaniuJeśli ustawisz
x:Name
właściwość na każdyTabItem
jako:<TabControl x:Name="MyTab" SelectionChanged="TabControl_SelectionChanged"> <TabItem x:Name="MyTabItem1" Header="One"/> <TabItem x:Name="MyTabItem2" Header="2"/> <TabItem x:Name="MyTabItem3" Header="Three"/> </TabControl>
Następnie możesz uzyskać dostęp do każdego
TabItem
na wydarzeniu:private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (MyTabItem1.IsSelected) // do your stuff if (MyTabItem2.IsSelected) // do your stuff if (MyTabItem3.IsSelected) // do your stuff }
źródło
Jeśli chcesz mieć zdarzenie tylko po wybraniu karty, to jest właściwy sposób:
<TabControl> <TabItem Selector.Selected="OnTabSelected" /> <TabItem Selector.Selected="OnTabSelected" /> <TabItem Selector.Selected="OnTabSelected" /> <!-- You can also catch the unselected event --> <TabItem Selector.Unselected="OnTabUnSelected" /> </TabControl>
I w swoim kodzie
private void OnTabSelected(object sender, RoutedEventArgs e) { var tab = sender as TabItem; if (tab != null) { // this tab is selected! } }
źródło
Nadal możesz wykorzystać to wydarzenie. Po prostu sprawdź, czy argument nadawcy jest kontrolką, na której Ci zależy, a jeśli tak, uruchom kod zdarzenia.
źródło
Wygenerowane zdarzenie bulgocze, dopóki nie zostanie obsłużone.
Ta część xaml poniżej jest wyzwalana
ui_Tab_Changed
po zmianieui_A_Changed
elementu wybranego wListView
zmianach, niezależnie odTabItem
zmiany w plikuTabControl
.<TabControl SelectionChanged="ui_Tab_Changed"> <TabItem> <ListView SelectionChanged="ui_A_Changed" /> </TabItem> <TabItem> <ListView SelectionChanged="ui_B_Changed" /> </TabItem> </TabControl>
Musimy skonsumować zdarzenie w
ui_A_Changed
(ui_B_Changed
i tak dalej):private void ui_A_Changed(object sender, SelectionChangedEventArgs e) { // do what you need to do ... // then consume the event e.Handled = true; }
źródło
To jest właściwe wydarzenie. Może nie jest prawidłowo podłączony?
<TabControl SelectionChanged="TabControl_SelectionChanged"> <TabItem Header="One"/> <TabItem Header="2"/> <TabItem Header="Three"/> </TabControl>
za kodem ...
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) { int i = 34; }
jeśli ustawię punkt przerwania w linii i = 34, zepsuje się on TYLKO, gdy zmienię zakładki, nawet jeśli karty mają elementy podrzędne i jeden z nich jest zaznaczony.
źródło
Jeśli używasz wzorca MVVM, korzystanie z programu obsługi zdarzeń jest niewygodne (i przerywa wzorzec). Zamiast tego można powiązać każdą indywidualną
Selector.IsSelected
właściwość TabItem z właściwością zależności w Viewmodel, a następnie obsłużyćPropertyChanged
procedurę obsługi zdarzeń. W ten sposób wiesz dokładnie, która karta została wybrana / odznaczona na podstawiePropertyName
i masz specjalny moduł obsługi dla każdej karty.Przykład:
MainView.xaml
<TabControl> <TabItem Header="My tab 1" Selector.IsSelected="{Binding IsMyTab1Selected}"> ... </TabItem> <TabItem Header="My tab 2" Selector.IsSelected="{Binding IsMyTab2Selected}"> ... </TabItem> </TabControl>
Przykład:
MainViewModel.cs
public bool IsMyTab1Selected { get { return (bool)GetValue(IsMyTab1SelectedProperty); } set { SetValue(IsMyTab1SelectedProperty, value); } } public static readonly DependencyProperty IsMyTab1SelectedProperty = DependencyProperty.Register("IsMyTab1Selected", typeof(bool), typeof(MainViewModel), new PropertyMetadata(true, new PropertyChangedCallback(MyPropertyChanged))); public bool IsMyTab2Selected { get { return (bool)GetValue(IsMyTab2SelectedProperty); } set { SetValue(IsMyTab2SelectedProperty, value); } } public static readonly DependencyProperty IsMyTab2SelectedProperty = DependencyProperty.Register("IsMyTab2Selected", typeof(bool), typeof(MainViewModel), new PropertyMetadata(false, new PropertyChangedCallback(MyPropertyChanged))); private void MyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (e.Property.Name == "IsMyTab1Selected") { // stuff to do } else if (e.Property.Name == "IsMyTab2Selected") { // stuff to do } }
Jeśli
MainViewModel
jestINotifyPropertyChanged
zamiastDependencyObject
, a następnie użyć zamiast tego:Przykład:
MainViewModel.cs
public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public MainViewModel() { PropertyChanged += handlePropertyChanged; } public bool IsMyTab1Selected { get { return _IsMyTab1Selected ; } set { if (value != _IsMyTab1Selected ) { _IsMyTab1Selected = value; OnPropertyChanged("IsMyTab1Selected "); } } } private bool _IsMyTab1Selected = false; public bool IsMyTab2Selected { get { return _IsMyTab2Selected ; } set { if (value != _IsMyTab2Selected ) { _IsMyTab2Selected = value; OnPropertyChanged("IsMyTab2Selected "); } } } private bool _IsMyTab2Selected = false; private void handlePropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "IsMyTab1Selected") { // stuff to do } else if (e.PropertyName == "IsMyTab2Selected") { // stuff to do } }
źródło
Ten kod wydaje się działać:
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) { TabItem selectedTab = e.AddedItems[0] as TabItem; // Gets selected tab if (selectedTab.Name == "Tab1") { // Do work Tab1 } else if (selectedTab.Name == "Tab2") { // Do work Tab2 } }
źródło
Jeśli ktoś korzysta z nowoczesnego interfejsu użytkownika WPF, nie może używać zdarzenia OnTabSelected, ale może użyć zdarzenia SelectedSourceChanged.
lubię to
<mui:ModernTab Layout="Tab" SelectedSourceChanged="ModernTab_SelectedSourceChanged" Background="Blue" AllowDrop="True" Name="tabcontroller" >
Kod C # to
private void ModernTab_SelectedSourceChanged(object sender, SourceEventArgs e) { var links = ((ModernTab)sender).Links; var link = this.tabcontroller.Links.FirstOrDefault(l => l.Source == e.Source); if (link != null) { var index = this.tabcontroller.Links.IndexOf(link); MessageBox.Show(index.ToString()); } }
źródło