2015-10-01 12 views
9

Ho un Datagrid WPF che ha una raccolta View Source con 3 livelli di raggruppamento su di esso.Nascondere l'espansore quando tutto il contenuto è compresso

ho designato il datagrid di utilizzare 3 espansori tale che assomiglia a questo:

Level 1 Expander 
<content> 
    Level 2 Expander 
    <content> 
     Level 3 Expander 
     <content> 

Livello 2 e Livello 1 sono solo titolo dei gruppi

Ho un secondo controllo che consente la utente per mostrare e nascondere gli elementi di livello 3 che funzionano legando l'espansore di Livello 3 a una proprietà booleana "IsVisible" nell'oggetto dietro.

 <!-- Style for groups under the top level. this is the style for how a sample is displayed --> 
     <GroupStyle> 
      <GroupStyle.ContainerStyle> 
       <Style TargetType="{x:Type GroupItem}"> 
        <Setter Property="Margin" Value="0,0,0,0" /> 
        <Setter Property="Template"> 
         <Setter.Value> 
          <ControlTemplate TargetType="{x:Type GroupItem}"> 

           <!-- The parent control that determines whether or not an item needs to be displayed. This holds all of the sub controls displayed for a sample --> 
           <Expander Margin="2" 
              Background="{Binding Path=Name, 
                   Converter={StaticResource SampleTypeToColourConverter}}" 
              IsExpanded="True" 
              Visibility="{Binding Path=Items[0].IsVisibleInMainScreen, 
                   Converter={StaticResource BoolToVisibilityConverter}}"> 

Questo approccio funziona in modo fantastico.

TUTTAVIA

Se l'utente deseleziona tutti gli elementi in un livello 3 di espansione, l'intestazione di livello 2 di espansione ancora mostra il che significa che di valore immobiliare è utilizzata up che mostra l'intestazione di un gruppo senza dati visibili.

Quello che vorrei è un modo per legare la visibilità del espansore di livello 2 per i relativi controlli figlio e dire "Se tutti i bambini sono visibili poi mostrare l'espansore, altrimenti comprimerlo"

è possibile?

+1

* Se tutti i bambini sono visibili, mostrare l'espansione, altrimenti comprimerlo * sembra un'attività di conversione. Hai già la proprietà 'IsVisibleInMainWindow', cambia quando i bambini sono compressi. Nota: 'Items' dovrebbe essere' ObservableCollection'. – Sinatr

+0

Puoi darci un xaml più completo incluso tutto l'expander? –

+0

Penso che abbiamo bisogno di più xaml. – PScr

risposta

3

ho trovato un modo piuttosto semplice e pulito, ma non perfetta, per raggiungere il tuo obiettivo. Questo dovrebbe fare il trucco se non hai troppi gruppi.

Ho appena aggiunto questo trigger al GroupItem ControlTemplate:

<ControlTemplate.Triggers> 
    <DataTrigger Binding="{Binding ElementName=IP, Path=ActualHeight}" Value="0"> 
     <Setter Property="Visibility" Value="Hidden"/> 
     <Setter Property="Height" Value="1"/> 
    </DataTrigger> 
</ControlTemplate.Triggers> 

Quando il ItemsPresenter (IP) ActualSize scende a zero, sarà quasi crollare l'intestazione.

Perché quasi?

Quando il controllo ottiene inizializzato e prima che si verifichi la legatura, il ItemPresenter ActualHeight è 0 e quando Visibility è impostato Collapsed, il ItemPresenter non viene reso affatto.

L'utilizzo di Visibility.Hidden consente a ItemsPresenter di passare alla fase di rendering e di essere misurati. Ho avuto successo di rilasciare Height in .4 px ma ho il sospetto che questo dipenda dal dispositivo.

+0

Ho scelto questa risposta perché ha funzionato quasi perfettamente fuori dalla scatola in puro xaml. Questo è il modo più semplice per farlo credo anche se le altre risposte hanno un merito a sé stante –

1

Questa non è una risposta diretta in quanto dovresti implementarla in modo specifico per le tue esigenze, ma in precedenza ho utilizzato una sovrascrittura del controllo griglia per creare un'assegnazione griglia dinamica dei membri, se non ci sono membri visibili allora nasconde la casella del gruppo genitore.

public class DynamicLayoutGrid : Grid 
{ 

     protected override void OnInitialized(EventArgs e) 
     { 
       //Hook up the loaded event (this is used because it fires after the visibility binding has occurred) 
      this.Loaded += new RoutedEventHandler(DynamicLayoutGrid_Loaded); 

      base.OnInitialized(e); 
     } 


     void DynamicLayoutGrid_Loaded(object sender, RoutedEventArgs e) 
     { 
      int numberOfColumns = ColumnDefinitions.Count; 
      int columnSpan = 0; 
      int rowNum = 0; 
      int columnNum = 0; 
      int visibleCount = 0; 

      foreach (UIElement child in Children) 
      { 
       //We only want to layout visible items in the grid 
       if (child.Visibility != Visibility.Visible) 
       { 
        continue; 
       } 
       else 
       { 
        visibleCount++; 
       } 

       //Get the column span of the element if it is not in column 0 as we might need to take this into account 
       columnSpan = Grid.GetColumnSpan(child); 

       //set the Grid row of the element 
       Grid.SetRow(child, rowNum); 

       //set the grid column of the element (and shift it along if the previous element on this row had a rowspan greater than 0 
       Grid.SetColumn(child, columnNum); 

       //If there isn't any columnspan then just move to the next column normally 
       if (columnSpan == 0) 
       { 
        columnSpan = 1; 
       } 

       //Move to the next available column 
       columnNum += columnSpan; 

       //Move to the next row and start the columns again 
       if (columnNum >= numberOfColumns) 
       { 
        rowNum++; 
        columnNum = 0; 
       } 
      } 

      if (visibleCount == 0) 
      { 
       if (this.Parent.GetType() == typeof(GroupBox)) 
       { 
        (this.Parent as GroupBox).Visibility = Visibility.Collapsed; 
       } 
      } 
     } 
    } 
3

Supponendo che si sta utilizzando un MVVM sorta di stile, si potrebbe associare invece a una proprietà del vostro oggetto gruppo che restituisce false se tutti i bambini sono invisibili:

public bool AreChildrenVisible { get { return _children.Any(x=>x.IsVisibleInMainScreen); } } 

In alternativa, passaggio la raccolta di articoli tramite una classe del convertitore per restituire la visibilità in base allo stato aggregato di tutti i sottoprioggetti nel gruppo.

0

Utilizzare l'implementazione IMultiValueConverter per convertire gli elementi in visibilità. Se tutti gli elementi della proprietà IsVisibleInMainScreen restituiscono true, il convertitore ritorna visibile altrimenti nascosto.

utilizzare il convertitore nello stesso luogo U utilizzato per convertire il primo elemento esempio originale

Problemi correlati