Я использую WPF и пытаюсь следовать шаблону MVVM. Наша команда решила использовать элемент управления Xceed DataGrid, и у меня возникли некоторые трудности при его установке в шаблон MVVM.
Одно требование, которое я должен выполнить, это то, что мне нужно знать, когда пользователь меняет фильтр столбцов в сетке. Мне известно, что в последней версии элемента управления DataGrid есть событие, которое вызывается для этого, но, к сожалению, мне приходится использовать более старую версию элемента управления.
После поиска некоторое время, я нашел эту запись. Это говорит о том, что мне нужно подключить обработчик INotifyCollectionChanged к каждому из возможных списков фильтров. Это работает, но также говорит, что мне нужно отсоединять обработчики всякий раз, когда изменяется источник строки сетки.
Мне удалось заставить его работать, когда я явно установил источник строки в коде позади страницы (и в моей первой попытке в ModelView с помощью прямой ссылки на представление gasp! )
Первая проблема, с которой я столкнулся, заключается в том, как сделать это, не имея логики в коде или в 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