2010-08-26 148 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; 
      } 
     } 
    } 
} 
相关问题