2010-08-26 15 views
7

Ho un TabControl su un UserControl supportato da un ViewModel e lo Visibility di uno degli elementi della scheda è associato a una proprietà sul ViewModel.WPF TabControl: selezionare una scheda diversa quando TabItem Visibility cambia

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

Quando il Visibility dei TabItem cambiamenti, collassa (pelli) nell'intestazione TabItem, ma continua mostrando il suo contenuto.

Voglio il TabControl a passare alla scheda visibile quando l'altra scheda è nascosta ed è stato un po 'sorpreso di scoprire che non si verifica automaticamente.

Allegare un gestore di eventi per l'SelectionChanged caso di TabControl dimostra che TabItem.IsSelected (e TabControl.SelectedItem) non è nemmeno influenzato quando il TabItem.Visibility modifiche (è questo un bug ?!).

Ho provato sia un trigger proprietà:

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

e un dato innescare:

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

non riesco a ottenere il trigger per lavorare, e non c'è VisibilityChanged evento che posso gestire, quindi sono un po 'bloccato e apprezzerei un po' di aiuto.

risposta

4

La classe TabItem ha un evento IsVisibleChanged che è possibile utilizzare.

+0

Ah, che farà! (+1) Non so perché non l'ho notato prima - suppongo che MSDN debba aver filtrato le proprietà ereditate al momento. Ho intenzione di non segnare questa è la risposta solo per vedere se qualcuno ha un suggerimento non code-behind, ma grazie mille. – Riko

2

Associare SelectedIndex di TabControl a una proprietà. E modifica il valore di questa proprietà nell'indice della scheda che desideri visualizzare ogni volta che cambi la visibilità per comprimere l'elemento della scheda.

1

È possibile aggiungere questo gestore di eventi al codice sottostante. Metterà alla prova il tuo controllo in primo luogo e le modifiche alla visibilità delle schede a causa dei binding.

Invece di fare questo OnLoaded ovviamente ha senso metterlo in una proprietà associata. (Auto selezione?) . Il codice è lo stesso. Viene chiamato in primo luogo e si collegano gli eventi a IsVisibleChanged. Quindi l'unico trucco è usare un lambda (Parameter binding) per ottenere l'istanza TabControl nel callback dell'evento. Sto postando questa soluzione, perché è più breve.

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; 
      } 
     } 
    } 
} 
Problemi correlati