gpt4 book ai didi

WPF,如何在观看 TypeDescriptor 时正确取消 Hook 处理程序

转载 作者:行者123 更新时间:2023-12-03 10:50:42 28 4
gpt4 key购买 nike

我正在使用 WPF,并尝试遵循 MVVM 模式。我们的团队已决定使用 Xceed DataGrid 控件,但我在使其适应 MVVM 模式时遇到了一些困难。
我必须满足的一个要求是我需要知道用户何时更改了网格上的列过滤器。我知道最新版本的 DataGrid 控件有一个为此引发的事件,但不幸的是,我必须使用旧版本的控件。
找了一会儿,找到了this邮政。它说我需要将 INotifyCollectionChanged 处理程序连接到每个可能的过滤器列表。这行得通,但它也表示,每当网格的行源发生变化时,我都需要解除处理程序的 Hook 。
当我在页面的代码隐藏中明确设置行源时,我能够让它工作(并且在我第一次尝试在 ModelView 中使用对 View 喘气的直接引用!)
不过,我遇到的第一个问题是如何在没有代码背后或 ViewModel 中的逻辑的情况下做到这一点。我的解决方案是扩展 DataGridControl 类并添加以下代码:

    private IDictionary<string, IList> _GridFilters = null;
public MyDataGridControl() : base()
{
TypeDescriptor.GetProperties(typeof(MyDataGridControl))["ItemsSource"].AddValueChanged(this, new EventHandler(ItemsSourceChanged));
}

void ItemsSourceChanged(object sender, EventArgs e)
{
UnsetGridFilterChangedEvent();
SetGridFilterChangedEvent();
}

public void SetGridFilterChangedEvent()
{
if (this.ItemsSource == null)
return;

DataGridCollectionView dataGridCollectionView = (DataGridCollectionView)this.ItemsSource;

_GridFilters = dataGridCollectionView.AutoFilterValues;

foreach (IList autofilterValues in _GridFilters.Values)
{
((INotifyCollectionChanged)autofilterValues).CollectionChanged += FilterChanged;
}
}

/*TODO: Possible memory leak*/
public void UnsetGridFilterChangedEvent()
{
if (_GridFilters == null)
return;

foreach (IList autofilterValues in _GridFilters.Values)
{
INotifyCollectionChanged notifyCollectionChanged = autofilterValues as INotifyCollectionChanged;

notifyCollectionChanged.CollectionChanged -= FilterChanged;
}

_GridFilters = null;
}
这导致我的下一个问题;我很确定在调用 ItemsSourceChanged 方法时,AutoFilterValues 的集合已经改变,所以我无法有效地解开处理程序。
我这样假设是对的吗?谁能想到一种更好的方法来管理这些处理程序,同时仍然允许我将该功能封装在我的扩展类中?
抱歉帖子的长度,并提前感谢您的帮助!
-Funger

最佳答案

您是正确的,此时 AutoFilterValues 已经更改,因此您将取消错误的处理程序,从而导致内存泄漏。

解决方案非常简单。做你正在做的事,但使用 List<IList>而不仅仅是引用 AutoFilterValues:

private List<IList> _GridFilters;

并使用 ToList()复制您设置处理程序的过滤器:
_GridFilters = dataGridCollectionView.AutoFilterValues.Values.ToList();

由于 _GridFilters 现在是 List<IList> ,您还必须更改循环:
foreach(IList autofilterValues in _GridFilters) 
...

这样做的原因是旧过滤器列表的实际列表被复制到 _GridFilters 中,而不是简单地引用 AutoFilterValues 属性。

这是一种很好的通用技术,适用于许多情况。

关于WPF,如何在观看 TypeDescriptor 时正确取消 Hook 处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4138399/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com