Чи є подія, обрана вкладкою, змінена у стандартному керуванні вкладками WPF


96

У WPF, чи є подія, за якою можна визначити, коли TabControlзмінюється вибрана вкладка?

Я пробував використовувати, TabControl.SelectionChangedале він запускається багато разів, коли вибір дитини у вкладці змінюється.

Відповіді:


122

Я прив’язав це до обробника, щоб він працював:

void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.Source is TabControl)
    {
      //do work when tab is changed
    }
}

2
Я думав, що це не працює, але тоді я зрозумів, що перевіряю senderзамістьe.Source
Гільєрмо Руффіно

4
або просто додайте, e.Handled = trueщоб запобігти пузирцю
Брок Хенслі,

77

Якщо ви встановите x:Nameвластивість для кожного TabItemяк:

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

Тоді ви зможете отримати доступ до кожного TabItemна заході:

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
}

50

Якщо ви просто хочете мати подію, коли вибрано вкладку, це правильний спосіб:

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

І у вашому коді

    private void OnTabSelected(object sender, RoutedEventArgs e)
    {
        var tab = sender as TabItem;
        if (tab != null)
        {
            // this tab is selected!
        }
    }

На жаль, наскільки це приємно виглядає, я не отримую вибраного властивості, доступного мені в xaml, лише IsSelected. Вибачте.
Фенрі

Я стою виправлений .... вид. DOH! Коли я намагаюся надрукувати вищезазначене у VS, це дає мені червоні бризки, отже, я вважав, що це було неправильно. АЛЕ коли я врізав його і просто наосліп F5 зробив це, на мій подив, це ПРАЦЮВАЛО. ГІ ?! Чому це працювало ТАК?
Фенрі

Як я можу отримати доступ до події "Selector.Selected" у коді замість
xaml

15

Ви все ще можете використати цю подію. Просто переконайтеся, що аргумент відправника є елементом керування, який вам насправді важливий, і якщо так, то запустіть код події.


4

Створена подія спливає, поки не буде оброблена.

Ця частина xaml нижче запускається ui_Tab_Changedпісля того, ui_A_Changedяк елемент, вибраний у ListViewзмінах, незалежно від TabItemзміни в TabControl.

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

Нам потрібно споживати подію в ui_A_Changedui_B_Changed, тощо):

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

3

Якщо ви використовуєте шаблон MVVM, то незручно (і порушує шаблон) використовувати обробник подій. Натомість ви можете прив’язати кожну властивість TabItem до Selector.IsSelectedвластивості залежності у вашій viewmodel, а потім обробити PropertyChangedобробник подій. Таким чином, ви точно знаєте, яку вкладку було вибрано / скасовано, PropertyNameі у вас є спеціальний обробник для кожної вкладки.

Приклад: MainView.xaml

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

Приклад: 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
 }
}

Якщо ваш MainViewModel, INotifyPropertyChangedа не DependencyObject, тоді скористайтеся цим:

Приклад: 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
 }
}

це у мене спрацювало;)
Blood-HaZaRd

2

Це правильна подія. Може, це не підключено правильно?

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

в коді позаду ....

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

якщо я встановлюю точку зупинки на рядку i = 34, вона ТІЛЬКИ ламається, коли я міняю вкладки, навіть коли вкладки мають дочірні елементи і вибрано один із них.


помістіть сітку на вкладку, вибравши рядок сітки, буде спливаюче виділення до вибраної події вкладки, якщо не обробляти її до того, як вона потрапить туди.
Paul Swetz,

2

Здається, цей код працює:

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

-1

Якщо хтось використовує сучасний інтерфейс користувача WPF, він не може використовувати подію OnTabSelected. Але вони можуть використовувати подію SelectedSourceChanged.

подобається це

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

Код 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());
          }            
    }

3
Використання аргументів сторонніх розробників ніколи не є рішенням, і їх слід вкрай не рекомендувати.
Стівен Борхес

@steven Я написав це для WPF MUI, і це теж не відповідь на запитання. але це може бути відповідь wpf mui user.Ось чому я поставив це як відповідь. дякую
Сандун Харшана
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.