我有同样的问题,它给了我很多头疼的。最后,我想到了这一点,可能不是最优雅的,但工作的解决方案(我不得不使它与多组合作,所以你会得到免费的功能:)。 主要思想是在排序发生前记住每个膨胀机的状态,并在排序完成后恢复。为了实现这一点,我已经:
在每一个手动展开或折叠记录它的状态(实际上我一直只是指出扩展扩展的)。作为扩展器标识符,我使用从绑定到扩展器的元素生成的标识)
在评估扩展器的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