2010-08-26 154 views
7

我有UserControl上的TabControl由ViewModel支持,其中一個選項卡項的Visibility綁定到ViewModel上的屬性。WPF TabControl - 當TabItem可見性發生變化時選擇不同的選項卡

<TabControl x:Name="myTabControl"> 
    <TabItem Header="Tab 1" /> 
    <TabItem Header="Tab 2" Visibility="{Binding HasData, Converter={StaticResource boolToVisibilityConverter}}"/> 
</TabControl> 

當的TabItem變化Visibility,它縮短(隱藏)的TabItem頭,但它仍然顯示其內容。

我希望TabControl切換到可見標籤,當其他標籤隱藏,有點驚訝發現它不會自動發生。

附加的事件處理程序SelectionChanged事件TabControl的顯示TabItem.IsSelected(和TabControl.SelectedItem)甚至沒有受到影響時TabItem.Visibility變化(這是一個錯誤?!)。

我都試過一個屬性觸發

<!-- This doesn't compile because of TargetName on the Setter, think you can only use it in Control Templates. 
     I don't know how to refer to the parent TabControl from within the TabItem style. --> 
    <TabControl.ItemContainerStyle> 
     <Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}"> 
      <Style.Triggers> 
       <Trigger Property="Visibility" Value="Collapsed"> 
        <Setter TargetName="myTabControl" Property="SelectedIndex" Value="0" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </TabControl.ItemContainerStyle> 

數據觸發

<!-- This doesn't quite work, it affects the Visibility of the TabItem's content too --> 
    <TabControl.Style> 
     <Style TargetType="{x:Type TabControl}" BasedOn="{StaticResource {x:Type TabControl}}"> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding Path=SelectedItem.Visibility, ElementName=tabControl}" 
          Value="Collapsed"> 
        <Setter Property="SelectedIndex" Value="0" /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </TabControl.Style> 

我不能讓觸發器的工作,而且也沒有VisibilityChanged事件我可以處理,所以我有點卡住,並希望得到一些幫助。

回答

4

TabItem類有一個可以使用的IsVisibleChanged事件。

+0

啊,那樣做! (+1)不知道爲什麼我沒有更早發現它 - 我想MSDN當時必須過濾出繼承的屬性。 我打算推遲標記這是答案,只是爲了看看有人有沒有代碼隱藏的建議,但非常感謝。 – Riko 2010-08-26 14:14:33

2

將TabControl的SelectedIndex綁定到屬性。將此屬性的值更改爲您希望在將可見性更改爲摺疊選項卡項目時顯示的選項卡的索引。

1

您可以將此事件處理程序添加到後面的代碼中。它將首先測試您的控件,並對由於綁定導致的選項卡可見性的更改進行測試。

而不是做這個OnLoaded當然這是完全有道理把它放到一個附加的屬性。 (自動選擇?) 。代碼是一樣的。您首先會打電話並將事件附加到IsVisibleChanged。然後唯一的技巧是使用lambda(Parameter binding)將TabControl實例放入事件回調中。我張貼這個解決方案,因爲它更短。

private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e) 
{ 
    var tabControl = (TabControl) sender; 
    // register visibility changed to react on changes 
    foreach (TabItem item in tabControl.Items) 
    { 
     item.IsVisibleChanged += (mSender, ev) => item_IsVisibleChanged(mSender, ev, tabControl); 
    } 
    // if current selected tab is invisible, find and select first visible one. 
    if (!((TabItem) tabControl.SelectedItem).IsVisible) 
    { 
     foreach (TabItem item in tabControl.Items) 
     { 
      if (item.IsVisible) 
      { 
       tabControl.SelectedItem = item; 
       return; 
      } 
     } 
    } 
} 

private static void item_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e, TabControl tabControl) 
{ 
    // just became IsVisible = false 
    if ((bool)e.NewValue == false) 
    { 
     if (tabControl == null) return; 
     ItemCollection items = tabControl.Items; 
     foreach (UIElement item in items) 
     { 
      if (item.IsVisible) 
      { 
       tabControl.SelectedItem = item; 
       return; 
      } 
     } 
    } 
} 
相關問題