¿Hay un evento modificado de pestaña seleccionada en el control de pestaña WPF estándar?

96

En WPF, ¿hay algún evento que pueda usarse para determinar cuándo TabControlcambia la pestaña seleccionada?

He intentado usarlo, TabControl.SelectionChangedpero se dispara muchas veces cuando se cambia la selección de un niño dentro de una pestaña.

Jon Kragh
fuente

Respuestas:

122

Até esto en el controlador para que funcione:

void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.Source is TabControl)
    {
      //do work when tab is changed
    }
}
Jon Kragh
fuente
2
Pensé que esto no estaba funcionando, pero luego me di cuenta de que estaba buscando en senderlugar dee.Source
Guillermo Ruffino
4
o simplemente agregue e.Handled = truepara evitar que burbujee
Brock Hensley
77

Si establece la x:Namepropiedad en cada uno 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>

Entonces puedes acceder a cada uno TabItemen el 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
}
inesperadokas
fuente
50

Si solo desea tener un evento cuando se selecciona una pestaña, esta es la forma correcta:

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

Y en tu codigo

    private void OnTabSelected(object sender, RoutedEventArgs e)
    {
        var tab = sender as TabItem;
        if (tab != null)
        {
            // this tab is selected!
        }
    }
MicBig
fuente
Desafortunadamente, por muy bueno que se vea este, no obtengo la propiedad Selected disponible para mí en xaml, solo IsSelected. Lo siento.
PHenry
Me quedo corregido ... algo así. DOH! Cuando trato de escribir sobre lo anterior en VS, me da los garabatos rojos, por lo que pensé que estaba mal. PERO cuando lo corté y pegué y lo F5 ciegamente, para mi asombro, funcionó. ¡¿HUH ?! ¿Por qué funcionó de esa manera?
PHenry
¿Cómo puedo acceder al evento "Selector.Selected" en código en lugar de xaml
Ahmed_Faraz
15

Todavía podrías usar ese evento. Simplemente verifique que el argumento del remitente sea el control que realmente le interesa y, de ser así, ejecute el código del evento.

Nidonocu
fuente
4

El evento generado se propaga hasta que se maneja.

Esta parte de xaml a continuación se activa ui_Tab_Changeddespués de ui_A_Changedque el elemento seleccionado en los ListViewcambios, independientemente del TabItemcambio en el TabControl.

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

Necesitamos consumir el evento en ui_A_Changed(y ui_B_Changed, etc.):

private void ui_A_Changed(object sender, SelectionChangedEventArgs e) {
  // do what you need to do
  ...
  // then consume the event
  e.Handled = true;
}
laminación
fuente
3

Si está utilizando el patrón MVVM, entonces es inconveniente (y rompe el patrón) usar el controlador de eventos. En su lugar, puede vincular la Selector.IsSelectedpropiedad de cada TabItem individual a una propiedad de dependencia en su modelo de vista y luego manejar el PropertyChangedcontrolador de eventos. De esa manera, sabrá exactamente qué pestaña se seleccionó / ​​deseleccionó según laPropertyName y tiene un controlador especial para cada pestaña.

Ejemplo: MainView.xaml

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

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

Si tu MainViewModeles en INotifyPropertyChangedlugar de DependencyObject, usa esto en su lugar:

Ejemplo: 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
fuente
esto funcionó para mí;)
Blood-HaZaRd
2

Ese es el evento correcto. ¿Quizás no está conectado correctamente?

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

en el código subyacente ...

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

si establezco un punto de interrupción en la línea i = 34, SOLO se rompe cuando cambio las pestañas, incluso cuando las pestañas tienen elementos secundarios y uno de ellos está seleccionado.

Muad'Dib
fuente
poner una cuadrícula en la pestaña, seleccionar una fila de la cuadrícula aparecerá en el evento de pestaña seleccionado si no se maneja antes de que llegue allí.
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
fuente
-1

Si alguien usa la IU moderna de WPF, no puede usar el evento OnTabSelected. Pero puede usar el evento SelectedSourceChanged.

Me gusta esto

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

El código C # es

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
fuente
3
Usar argumentos de terceros nunca es una solución y debe desalentarse mucho.
Steven Borges
@steven escribí esto para WPF MUI y esta no es la respuesta a la pregunta también. pero esta podría ser la respuesta wpf mui user. Es por eso que pongo esto como respuesta. gracias
Sandun Harshana