2012-03-28 51 views
1

我有一個WPF數據網格,其中我通過某個屬性對數據進行分組。 所有標準的東西。 但是,當我單擊某個列標題按該列進行排序時,它會摺疊所有組。如果可能,我想盡量避免這種情況。 我可以捕獲DataGrid的排序事件,並且如果我嘗試將組的擴展器設置爲「IsExpanded」,則它不起作用,因爲它看起來IsExpanded已經爲真,即使它未顯示展開。防止DataGrid組排序崩潰?

它似乎是標準的行爲,而不僅僅是我的數據,所以任何人都可以給出如何實現這一點的例子會很好。

的XAML我已經得到了數據網格是這樣的:

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

感謝

回答

4

我有同樣的問題,它給了我很多頭疼的。最後,我想到了這一點,可能不是最優雅的,但工作的解決方案(我不得不使它與多組合作,所以你會得到免費的功能:)。 主要思想是在排序發生前記住每個膨脹機的狀態,並在排序完成後恢復。爲了實現這一點,我已經:

  1. 在每一個手動展開或摺疊記錄它的狀態(實際上我一直只是指出擴展擴展的)。作爲擴展器標識符,我使用從綁定到擴展器的元素生成的標識)

  2. 在評估擴展器的IsExpanded屬性時使用的轉換器檢查當前擴展器狀態是否在已保存狀態列表中,並相應地返回IsExpanded值。

擴展在GroupStyle:

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

請以你的類型的控制,如果neccessary的AncestorType窗口部分...

代碼在瀏覽:

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

轉換器:

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]; 
    } 
} 

我知道通過在這裏使用任意分隔符來生成擴展器的標識符並不是最佳實踐,我很樂意提供有關如何改善此問題的建議。

的完整代碼可以在這裏:<Expander IsExpanded="True">ExpandersForSO2

0

你能不能簡單地通過增加改變<Expander>節點?