Existe um evento de mudança de guia selecionada no controle de guia WPF padrão

96

No WPF, há um evento que pode ser usado para determinar quando uma TabControlguia selecionada muda?

Eu tentei usar, TabControl.SelectionChangedmas ele está sendo disparado muitas vezes quando a seleção de uma criança em uma guia é alterada.

Jon Kragh
fonte

Respostas:

121

Amarrei isso no manipulador para fazer funcionar:

void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.Source is TabControl)
    {
      //do work when tab is changed
    }
}
Jon Kragh
fonte
2
Achei que não estava funcionando, mas então percebi que estava verificando em sendervez dee.Source
Guillermo Ruffino
4
ou apenas adicione e.Handled = truepara evitar que borbulhe
Brock Hensley,
77

Se você definir a x:Namepropriedade para cada um TabItemcomo:

<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>

Então você pode acessar cada um TabItemno evento:

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
}
inesperado
fonte
50

Se você quiser apenas ter um evento quando uma guia for selecionada, esta é a maneira correta:

<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>

E em seu código

    private void OnTabSelected(object sender, RoutedEventArgs e)
    {
        var tab = sender as TabItem;
        if (tab != null)
        {
            // this tab is selected!
        }
    }
MicBig
fonte
Infelizmente, por mais legal que este pareça, não consigo a propriedade Selected disponível para mim no xaml, apenas IsSelected. Desculpe.
PHenry
Eu estou corrigido .... mais ou menos. DOH! Quando tento digitar sobre o acima no VS, aparece um rabisco vermelho, portanto, pensei que estava errado. MAS quando eu cortei e passei e cegamente F5, para meu espanto, FUNCIONOU. HÃ?! Por que funcionou ASSIM?
PHenry
Como posso acessar o evento "Selector.Selected" no código em vez de xaml
Ahmed_Faraz
15

Você ainda pode usar esse evento. Apenas verifique se o argumento do remetente é o controle com o qual você realmente se importa e, se for o caso, execute o código do evento.

Nidonocu
fonte
4

O evento gerado está borbulhando até que seja tratado.

Esta parte xaml abaixo é acionada ui_Tab_Changedapós ui_A_Changedquando o item selecionado nas ListViewalterações, independentemente da TabItemalteração no TabControl.

<TabControl SelectionChanged="ui_Tab_Changed">
  <TabItem>
    <ListView SelectionChanged="ui_A_Changed" />
  </TabItem>
  <TabItem>
    <ListView SelectionChanged="ui_B_Changed" />
  </TabItem>
</TabControl>

Precisamos consumir o evento em ui_A_Changed(e ui_B_Changed, e assim por diante):

private void ui_A_Changed(object sender, SelectionChangedEventArgs e) {
  // do what you need to do
  ...
  // then consume the event
  e.Handled = true;
}
rolando
fonte
2

Esse é o evento correto. Talvez não esteja conectado corretamente?

<TabControl SelectionChanged="TabControl_SelectionChanged">
    <TabItem Header="One"/>
    <TabItem Header="2"/>
    <TabItem Header="Three"/>
</TabControl>

no codebehind ....

private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    int i = 34;
}

se eu definir um ponto de interrupção na linha i = 34, ele SOMENTE quebra quando eu mudo as guias, mesmo quando as guias têm elementos filho e um deles está selecionado.

Muad'Dib
fonte
coloque uma grade na guia, selecionar uma linha de grade irá borbulhar até o evento da guia selecionada se não for tratado antes de chegar lá.
Paul Swetz
2

Este código parece funcionar:

    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
fonte
1

Se você estiver usando o padrão MVVM, é inconveniente (e quebra o padrão) usar o manipulador de eventos. Em vez disso, você pode vincular cada Selector.IsSelectedpropriedade TabItem individual a uma propriedade de dependência em seu modelo de visualização e, em seguida, manipular o PropertyChangedmanipulador de eventos. Dessa forma, você sabe exatamente qual guia foi selecionada / desmarcada com base noPropertyName e tem um manipulador especial para cada guia.

Exemplo: MainView.xaml

<TabControl>
 <TabItem Header="My tab 1" Selector.IsSelected="{Binding IsMyTab1Selected}"> ... </TabItem>
 <TabItem Header="My tab 2" Selector.IsSelected="{Binding IsMyTab2Selected}"> ... </TabItem>
</TabControl>

Exemplo: 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
 }
}

Se você MainViewModelé, em INotifyPropertyChangedvez deDependencyObject , use este:

Exemplo: 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
fonte
-1

Se alguém usa WPF Modern UI, não pode usar o evento OnTabSelected, mas pode usar o evento SelectedSourceChanged.

como isso

<mui:ModernTab Layout="Tab" SelectedSourceChanged="ModernTab_SelectedSourceChanged" Background="Blue" AllowDrop="True" Name="tabcontroller" >

O código C # é

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
fonte
3
Usar argumentos de terceiros nunca é uma solução e deve ser altamente desencorajado.
Steven Borges
@steven eu escrevi isso para WPF MUI e esta não é uma resposta à pergunta também. mas poderia ser uma resposta wpf mui user. É por isso que coloquei isso como uma resposta. obrigado
Sandun Harshana