2010-08-26 19 views
7

Tengo un TabControl en un UserControl respaldado por un ViewModel, y el Visibility de uno de los elementos de tabulación está vinculado a una propiedad en el ViewModel.WPF TabControl - Seleccione una pestaña diferente cuando la visibilidad de TabItem cambie

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

Cuando el Visibility de los cambios TabItem, se colapsa (oculta) la cabecera TabItem, pero sigue mostrando su contenido.

Quiero TabControl a cambiar a la pestaña visible cuando la otra pestaña está oculta, y me sorprendió un poco descubrir que esto no sucede automáticamente.

Instalación de un controlador de eventos al SelectionChanged caso de TabControl muestra que TabItem.IsSelected (y TabControl.SelectedItem) no está aún afectado cuando el TabItem.Visibility cambios (es esto un error ?!).

He intentado tanto un disparador propiedad:

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

y un conjunto de datos desencadenar:

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

no puedo conseguir los disparadores para trabajar, y no hay VisibilityChanged evento que puedo manejar, así que estoy algo atrapado y agradecería algo de ayuda.

Respuesta

4

La clase TabItem tiene un evento IsVisibleChanged que puede usar.

+0

¡Eso sí! (+1) No sé por qué no lo detecté antes. Supongo que MSDN debe haber filtrado las propiedades heredadas en ese momento. Voy a postergar la marca esta es la respuesta solo para ver si alguien tiene una sugerencia sin código subyacente, pero muchas gracias. – Riko

2

Enlazar SelectedIndex of TabControl a una propiedad. Y cambie el valor de esta propiedad al índice de la pestaña que desea visualizar cada vez que cambie la visibilidad al colapso del elemento de la pestaña.

1

Puede agregar este controlador de eventos al código que se encuentra detrás. En primer lugar, pondrá a prueba su control y los cambios en la visibilidad de las pestañas debido a los enlaces.

En lugar de hacer esto OnLoaded, por supuesto, tiene sentido poner esto en una propiedad adjunta. (¿Selección automática?) . El código es el mismo Primero se te llama y se adjuntan eventos a IsVisibleChanged. Entonces, el único truco es usar un lambda (enlace de parámetros) para obtener la instancia de TabControl en la devolución de llamada del evento. Estoy publicando esta solución, porque es más corta.

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; 
      } 
     } 
    } 
} 
Cuestiones relacionadas