2012-03-28 121 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>节点?