2012-03-28 16 views
1

Ich habe ein WPF-Datengrid, in dem ich Daten nach einer bestimmten Eigenschaft gruppiere. Alle Standard-Sachen. Wenn ich jedoch auf einen der Spaltenköpfe klicke, um nach dieser Spalte zu sortieren, werden alle Gruppen minimiert. Ich möchte das nach Möglichkeit verhindern. Ich kann das Sortierungsereignis des DataGrids abfangen, und wenn ich versuche, den Expander für die Gruppe auf "IsExpanded" zu setzen, hat dies keine Auswirkungen, da IsExpanded bereits wahr ist, obwohl es nicht erweitert angezeigt wird.Verhindern, dass DataGrid-Gruppen beim Sortieren kollabieren?

Es scheint Standardverhalten zu sein und nicht nur mit meinen Daten, also kann jedes Beispiel jemand geben, wie man dies erreichen würde, wäre großartig.

die XAML ich für das Datenraster bekommen haben ist als solche:

<DataGrid ItemsSource="{Binding Items}" x:Name="dataGrid"> 
    <DataGrid.GroupStyle> 
     <GroupStyle> 
      <GroupStyle.ContainerStyle> 
       <Style TargetType="GroupItem"> 
        <Setter Property="Template"> 
         <Setter.Value> 
          <ControlTemplate> 
           <Expander> 
            <Expander.Header> 
             <TextBlock> 
            <TextBlock.Text> 
             <MultiBinding StringFormat="{}{0} ({1} Items)"> 
              <MultiBinding.Bindings> 
               <Binding Path="Name"/> 
               <Binding Path="ItemCount"/> 
              </MultiBinding.Bindings> 
             </MultiBinding> 
            </TextBlock.Text> 
             </TextBlock> 
            </Expander.Header> 
            <ItemsPresenter/> 
           </Expander> 
          </ControlTemplate> 
         </Setter.Value> 
        </Setter> 
       </Style> 
      </GroupStyle.ContainerStyle> 
     </GroupStyle> 
    </DataGrid.GroupStyle> 
</DataGrid> 

Dank

Antwort

4

ich hatte das gleiche Problem haben, und es gab mir eine Menge Kopfschmerzen. Schließlich bin ich zu dieser, wahrscheinlich nicht die eleganteste, aber funktionierende Lösung gekommen (ich musste es mit Multi-Gruppierung arbeiten lassen, damit Sie diese Funktionalität gratis bekommen). Grundidee ist es, den Status jedes Expanders vor dem Sortieren zu speichern und nach dem Sortieren wiederherzustellen. Um dies zu erreichen, ich habe:

  1. Auf jedem manuellen Aufweiten oder seinen Zustand aufgezeichnet Kollabieren (eigentlich halte ich besagen nur aus expandiertem Expandern). Als expander identifier verwende ich die generierte ID aus dem Element, das mit dem Expander verknüpft ist.

  2. Bei der Auswertung der Expanders IsExpanded property used converter, der prüft, ob der aktuelle Expanderzustand in der Liste der gespeicherten Zustände ist und den IsExpanded Wert entsprechend zurückgibt.

Expander in Group:

<Expander x:Name="exp" Expanded="exp_Expanded" Collapsed="exp_Collapsed" > 
     <Expander.IsExpanded> 
      <MultiBinding Converter="{StaticResource ResourceKey=expanderStateConverter}" Mode="OneWay" > 
       <Binding Mode="OneWay"/> 
       <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}" Path="ExpandersStates" /> 
      </MultiBinding> 
     </Expander.IsExpanded> 
    <!-- ... the rest of the boring expander code --> 
    </Expander> 

Ersetzen Sie das AncestorType Fensterteil mit Ihrer Art von Kontrolle, wenn nötig ...

-Code in Aussicht:

public List<string> ExpandersStates {get; set; } 
    private void exp_Expanded(object sender, RoutedEventArgs e) 
    { 
     ExpandCollapseExpander(sender as Expander, e, true); 
    } 

    private void exp_Collapsed(object sender, RoutedEventArgs e) 
    { 
     ExpandCollapseExpander(sender as Expander, e, false); 
    } 

    private void ExpandCollapseExpander(Expander exp, RoutedEventArgs e, bool doExpand) 
    { 
     CollectionViewGroup collectionViewGroup = exp.DataContext as CollectionViewGroup; 
     if (collectionViewGroup == null) 
     { 
      return; 
     } 
     string viewGroupId = FormViewGroupIdentifier(collectionViewGroup, null); 
     if (doExpand) 
     { 
      if (!ExpandersStates.Contains(viewGroupId)) 
      { 
       ExpandersStates.Add(viewGroupId); 
      } 
     } 
     else 
     { 
      ExpandersStates.Remove(viewGroupId); 
     } 
     e.Handled = true; 
    } 

    public static string FormViewGroupIdentifier(CollectionViewGroup collectionViewGroup, string sufix) 
    { 
     string formViewGroupIdentifier = collectionViewGroup.Name + sufix; 
     CollectionViewGroup parentgroup = GetParent(collectionViewGroup); 
     if (parentgroup == null) 
     { 
      return formViewGroupIdentifier; 
     } 
     else 
     { 
      return FormViewGroupIdentifier(parentgroup, "putHereSomeDelimiterWhichWillNeverOccurInYourGroupingProperty" + formViewGroupIdentifier); 
     } 
    } 

    private static CollectionViewGroup GetParent(CollectionViewGroup collectionViewGroup) 
    { 
     Type type = collectionViewGroup.GetType(); 
     if (type.Name == "CollectionViewGroupRoot") 
     {//if we are at the root level return null as there is no parent 
      return null; 
     } 

     CollectionViewGroup parentgroup 
      = type.GetProperty("Parent", System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic) 
      .GetValue(collectionViewGroup, null) as CollectionViewGroup; 
     return parentgroup; 
    } 

Converter:

public class ExpanderStateConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     CollectionViewGroup collectionViewGroup = values[0] as CollectionViewGroup; 
     List<string> expandersStates = values[1] as List<string>; 
     if (!expandersStates.Any()) 
     {//prevent forming group identifier to speed up process as there are no expanded expanders anyway 
      return false; 
     } 

     string groupId = MainWindow.FormViewGroupIdentifier(collectionViewGroup, null); 
     bool contains = expandersStates.Contains(groupId); 
     return contains; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     return new object[2]; 
    } 
} 

Ich bin mir bewusst, dass das Generieren von Bezeichnern für Expanders mit beliebigem Delimiter hier nicht die beste Vorgehensweise ist, und ich bin offen für Vorschläge, wie Sie das verbessern können.

Vollcode hier: ExpandersForSO2

0

Könnten Sie nicht einfach den <Expander> Knoten durch Hinzufügen: <Expander IsExpanded="True">?

Verwandte Themen