我正在使用 WPF,并尝试遵循 MVVM 模式。我们的团队已决定使用 Xceed DataGrid 控件,但我在使其适应 MVVM 模式时遇到了一些困难。
我必须满足的一个要求是我需要知道用户何时更改了网格上的列过滤器。我知道最新版本的 DataGrid 控件有一个为此引发的事件,但不幸的是,我必须使用旧版本的控件。
找了一阵子,找到了这个帖子。它说我需要将 INotifyCollectionChanged 处理程序连接到每个可能的过滤器列表。这行得通,但它也表示,每当网格的行源发生变化时,我都需要解除处理程序的挂钩。
当我在页面的代码隐藏中显式设置行源时,我能够让它工作(并且在我第一次尝试在 ModelView 中使用对视图喘气的直接引用!)
不过,我遇到的第一个问题是如何在没有代码背后或 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