Y a-t-il un événement modifié d'onglet sélectionné dans le contrôle d'onglet WPF standard?

96

Dans WPF, existe-t-il un événement qui peut être utilisé pour déterminer quand un TabControlonglet sélectionné change?

J'ai essayé d'utiliser TabControl.SelectionChangedmais il est déclenché plusieurs fois lorsque la sélection d'un enfant dans un onglet est modifiée.

Jon Kragh
la source

Réponses:

122

J'ai lié ceci dans le gestionnaire pour que cela fonctionne:

void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.Source is TabControl)
    {
      //do work when tab is changed
    }
}
Jon Kragh
la source
2
Je pensais que cela ne fonctionnait pas mais j'ai réalisé que je vérifiais à la senderplace dee.Source
Guillermo Ruffino
4
ou ajoutez simplement e.Handled = truepour l'empêcher de bouillonner
Brock Hensley
77

Si vous définissez la x:Namepropriété sur each TabItemcomme:

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

Ensuite, vous pouvez accéder à chacun TabItemlors de l'événement:

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
}
inattendu
la source
50

Si vous souhaitez simplement avoir un événement lorsqu'un onglet est sélectionné, voici la bonne façon:

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

Et dans votre code

    private void OnTabSelected(object sender, RoutedEventArgs e)
    {
        var tab = sender as TabItem;
        if (tab != null)
        {
            // this tab is selected!
        }
    }
MicBig
la source
Malheureusement, aussi beau que celui-ci en ait l'air, je ne reçois pas la propriété Selected à ma disposition dans xaml, juste le IsSelected. Désolé.
PHenry
Je suis corrigé ... en quelque sorte. DOH! Quand j'essaie de taper ce qui précède dans VS, cela me donne les squigglies rouges, donc j'ai pensé que c'était faux. MAIS quand je l'ai coupé et collé et que je l'ai simplement F5 aveuglément, à mon grand étonnement, CELA A MARCHE. HUH?! Pourquoi cela a-t-il fonctionné de cette façon?
PHenry
Comment puis-je accéder à l'événement "Selector.Selected" dans le code au lieu de xaml
Ahmed_Faraz
15

Vous pouvez toujours utiliser cet événement. Vérifiez simplement que l'argument expéditeur est le contrôle qui vous tient vraiment à cœur et si c'est le cas, exécutez le code d'événement.

Nidonocu
la source
4

L'événement généré bouillonne jusqu'à ce qu'il soit traité.

Cette partie xaml ci-dessous se déclenche ui_Tab_Changedaprès le ui_A_Changedmoment où l'élément sélectionné dans les ListViewmodifications, quel que soit le TabItemchangement dans le TabControl.

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

Nous devons consommer l'événement dans ui_A_Changed(et 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;
}
roulant
la source
3

Si vous utilisez le modèle MVVM, il n'est pas pratique (et rompt le modèle) d'utiliser le gestionnaire d'événements. Au lieu de cela, vous pouvez lier la Selector.IsSelectedpropriété de chaque TabItem à une propriété de dépendance dans votre viewmodel, puis gérer le PropertyChangedgestionnaire d'événements. De cette façon, vous savez exactement quel onglet a été sélectionné / désélectionné en fonction de PropertyNameet vous disposez d'un gestionnaire spécial pour chaque onglet.

Exemple: MainView.xaml

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

Exemple: 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 votre MainViewModelest INotifyPropertyChangedplutôt que DependencyObject, utilisez plutôt ceci:

Exemple: 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
la source
cela a fonctionné pour moi;)
Blood-HaZaRd
2

C'est l'événement correct. Peut-être que ce n'est pas correctement câblé?

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

dans le code derrière ...

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

si je définis un point d'arrêt sur la ligne i = 34, il se casse UNIQUEMENT lorsque je change d'onglets, même lorsque les onglets ont des éléments enfants et que l'un d'eux est sélectionné.

Muad'Dib
la source
placez une grille dans l'onglet, la sélection d'une ligne de grille fera remonter jusqu'à l'événement sélectionné de l'onglet si elle n'est pas gérée avant d'y arriver.
Paul Swetz
2

Ce code semble fonctionner:

    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
la source
-1

Si quelqu'un utilise WPF Modern UI, il ne peut pas utiliser l'événement OnTabSelected, mais il peut utiliser l'événement SelectedSourceChanged.

comme ça

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

Le code C # est

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
la source
3
L'utilisation d'arguments tiers n'est jamais une solution et doit être fortement déconseillée.
Steven Borges
@steven J'ai écrit ceci pour WPF MUI et ce n'est pas non plus une réponse à la question, mais cela pourrait être la réponse wpf mui user.C'est pourquoi je mets cela comme réponse. merci
Sandun Harshana