WPFを使用していて、MVVMパターンに従おうとしています。私たちのチームはXceedDataGridコントロールを使用することを決定しましたが、MVVMパターンに適合させるのにいくつかの問題があります。
私が満たさなければならない1つの要件は、ユーザーがグリッド上の列フィルターをいつ変更するかを知る必要があることです。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のコレクションが既に変更されていると確信しているため、ハンドラーのフックを効果的に解除することはできません。
私はこれを想定するのは正しいですか?そして、拡張クラス内にその機能をカプセル化したままにして、これらのハンドラーを管理するためのより良い方法を誰かが考えることができますか?
投稿の長さについて申し訳ありませんが、助けてくれてありがとう!
-ファンガー