Czy w standardowej kontrolce karty WPF istnieje zdarzenie Wybrano zmienioną kartę

98

Czy w WPF istnieje zdarzenie, którego można użyć do określenia, kiedy TabControlzmienia się wybrana karta?

Próbowałem używać, TabControl.SelectionChangedale jest wielokrotnie uruchamiany, gdy zmienia się wybór dziecka w zakładce.

Jon Kragh
źródło

Odpowiedzi:

123

Zawiązałem to w programie obsługi, aby działało:

void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.Source is TabControl)
    {
      //do work when tab is changed
    }
}
Jon Kragh
źródło
2
Myślałem, że to nie działa, ale potem zdałem sobie sprawę, że sprawdzam senderzamiaste.Source
Guillermo Ruffino
4
lub po prostu dodaj, e.Handled = trueaby zapobiec bulgotaniu
Brock Hensley
80

Jeśli ustawisz x:Namewłaściwość na każdy TabItemjako:

<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 TabItemna 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
}
nieoczekiwane
źródło
51

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!
        }
    }
MicBig
źródło
Niestety tak ładnie, jak wygląda to, nie dostaję właściwości Selected dostępnej dla mnie w xaml, tylko IsSelected. Przepraszam.
PHenry
Stoję poprawiony ... w pewnym sensie. DOH! Kiedy próbuję napisać o powyższym w VS, daje mi to czerwone zawijasy, więc pomyślałem, że to źle. ALE kiedy go wyciąłem i wkleiłem i po prostu na ślepo F5 to, ku mojemu zdziwieniu, DZIAŁAŁO. Hę ?! Dlaczego to tak zadziałało?
PHenry
Jak mogę uzyskać dostęp do zdarzenia „Selector.Selected” w kodzie zamiast w
XAML
15

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.

Nidonocu
źródło
4

Wygenerowane zdarzenie bulgocze, dopóki nie zostanie obsłużone.

Ta część xaml poniżej jest wyzwalana ui_Tab_Changedpo zmianie ui_A_Changedelementu wybranego w ListViewzmianach, niezależnie od TabItemzmiany w pliku TabControl.

<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_Changedi tak dalej):

private void ui_A_Changed(object sender, SelectionChangedEventArgs e) {
  // do what you need to do
  ...
  // then consume the event
  e.Handled = true;
}
walcowanie
źródło
3

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.

Muad'Dib
źródło
umieść siatkę na karcie, wybranie wiersza siatki spowoduje przejście do zdarzenia wybranego na karcie, jeśli nie zostanie obsłużone, zanim tam dotrze.
Paul Swetz
3

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.IsSelectedwłaściwość TabItem z właściwością zależności w Viewmodel, a następnie obsłużyć PropertyChangedprocedurę obsługi zdarzeń. W ten sposób wiesz dokładnie, która karta została wybrana / odznaczona na podstawie PropertyNamei 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 MainViewModeljest INotifyPropertyChangedzamiast DependencyObject, 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
 }
}
Nikola Novak
źródło
to zadziałało;)
Blood-HaZaRd
2

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
        }
    }
Mc_Topaz
źródło
-1

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());
          }            
    }
Sandun Harshana
źródło
3
Korzystanie z argumentów osób trzecich nigdy nie jest rozwiązaniem i należy ich zdecydowanie odradzać.
Steven Borges
@steven Napisałem to dla WPF MUI i to też nie jest odpowiedź na pytanie. ale to może być odpowiedź użytkownika wpf mui. Dlatego umieściłem to jako odpowiedź. dziękuję
Sandun Harshana