มี Selected Tab Changed Event ใน WPF Tab Control มาตรฐานหรือไม่


99

ใน WPF มีเหตุการณ์ที่สามารถใช้เพื่อกำหนดเมื่อTabControlแท็บที่เลือกเปลี่ยนไปหรือไม่?

ฉันได้ลองใช้แล้วTabControl.SelectionChangedแต่มันถูกยิงหลายครั้งเมื่อมีการเปลี่ยนแปลงการเลือกของเด็กในแท็บ

คำตอบ:


126

ฉันผูกสิ่งนี้ไว้ในตัวจัดการเพื่อให้ใช้งานได้:

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

2
ฉันคิดว่ามันใช้ไม่ได้ แต่แล้วฉันก็รู้ว่าฉันกำลังตรวจสอบsenderแทนe.Source
Guillermo Ruffino

4
หรือเพิ่มe.Handled = trueเพื่อป้องกันไม่ให้เดือด
Brock Hensley

81

หากคุณตั้งค่า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
}

51

หากคุณต้องการเพียงแค่มีเหตุการณ์เมื่อเลือกแท็บนี่เป็นวิธีที่ถูกต้อง:

<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 ขออภัย.
PHenry

ผมยืนแก้ไข .... แบบ. DOH! เมื่อฉันพยายามพิมพ์เกี่ยวกับข้างบนใน VS มันทำให้ฉันได้สีแดง squigglies ดังนั้นฉันจึงคิดว่ามันผิด แต่เมื่อฉันตัดมันลงไปและเพียงแค่ F5 ก็สุ่มสี่สุ่มห้ามันก็ใช้งานได้ ฮะ?! ทำไมมันถึงได้ผลเช่นนั้น?
PHenry

1
ฉันจะเข้าถึงเหตุการณ์ "Selector.Selected" ในรหัสแทน xaml ได้อย่างไร
Ahmed_Faraz

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_Changed(และui_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

นั่นคือเหตุการณ์ที่ถูกต้อง อาจจะไม่ได้ต่อสายอย่างถูกต้อง?

<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

3

หากคุณใช้รูปแบบ MVVM ไม่สะดวก (และแตกรูปแบบ) ที่จะใช้ตัวจัดการเหตุการณ์ แต่คุณสามารถผูกแต่ละSelector.IsSelectedคุณสมบัติของ TabItem กับคุณสมบัติการพึ่งพาใน 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
 }
}

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 Modern UI จะไม่สามารถใช้เหตุการณ์ 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 Borges

@steven ฉันเขียนสิ่งนี้สำหรับ WPF MUI และนี่ก็ไม่ใช่คำตอบสำหรับคำถามเช่นกัน แต่นี่อาจเป็นคำตอบของผู้ใช้ wpf mui นั่นคือเหตุผลที่ฉันใส่สิ่งนี้เป็นคำตอบ ขอบคุณ
Sandun Harshana
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.