Dans WPF, existe-t-il un événement qui peut être utilisé pour déterminer le moment où un onglet sélectionné de TabControl
change?
J'ai essayé d'utiliser TabControl.SelectionChanged
, mais il est renvoyé plusieurs fois lorsque la sélection d'un enfant dans un onglet est modifiée.
J'ai attaché ceci dans le gestionnaire pour le faire fonctionner:
void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.Source is TabControl)
{
//do work when tab is changed
}
}
Si vous définissez la propriété x:Name
sur chaque TabItem
comme suit:
<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 à chaque TabItem
lors 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
}
Si vous voulez juste avoir un événement quand un onglet est sélectionné, ceci est le bon moyen:
<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!
}
}
Vous pouvez toujours utiliser cet événement. Il suffit de vérifier que l'argument de l'expéditeur est le contrôle qui vous tient à coeur et, le cas échéant, exécutez le code de l'événement.
L'événement généré bouillonne jusqu'à ce qu'il soit géré.
Cette partie xaml ci-dessous déclenche ui_Tab_Changed
après ui_A_Changed
lorsque l'élément sélectionné dans la variable ListView
change, indépendamment de la modification de TabItem
dans la variable TabControl
.
<TabControl SelectionChanged="ui_Tab_Changed">
<TabItem>
<ListView SelectionChanged="ui_A_Changed" />
</TabItem>
<TabItem>
<ListView SelectionChanged="ui_B_Changed" />
</TabItem>
</TabControl>
Nous devons utiliser 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;
}
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
}
}
C'est le bon événement. Peut-être que ce n'est pas câblé correctement?
<TabControl SelectionChanged="TabControl_SelectionChanged">
<TabItem Header="One"/>
<TabItem Header="2"/>
<TabItem Header="Three"/>
</TabControl>
dans le codebehind ....
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 cassera UNIQUEMENT lorsque je changerai d'onglet, même lorsque les onglets ont des éléments enfants et que l'un d'eux est sélectionné.
Si vous utilisez le modèle MVVM, il est peu pratique (et casse le modèle) d'utiliser le gestionnaire d'événements. Au lieu de cela, vous pouvez lier chaque propriété Selector.IsSelected
de TabItem à une propriété de dépendance dans votre modèle de vue, puis gérer le gestionnaire d'événements PropertyChanged
. De cette façon, vous savez exactement quel onglet a été sélectionné/désélectionné en fonction de la variable PropertyName
et 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 MainViewModel
est INotifyPropertyChanged
plutôt que DependencyObject
, utilisez 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
}
}