質問

私はWPFを使用しており、MVVMパターンに従っています。私たちのチームは、XCeed Datagridコントロールを使用することを決定しましたが、MVVMパターンに適合させるのに苦労しています。

私が満たさなければならない要件の1つは、ユーザーがグリッド上の列フィルターをいつ変更するかを知る必要があることです。 Datagridコントロールの最新バージョンには、このために提起されるイベントがあることを知っていますが、残念ながら、古いバージョンのコントロールを使用する必要があります。

しばらく検索した後、私は見つけました これ 役職。 InotifyCollectionChanged Handlerを、可能なフィルターの各リストにフックする必要があると述べています。これは機能しますが、グリッドの行ソースが変更されるたびにハンドラーを外す必要があるとも言います。

ページのCodeBehindで行のソースを明示的に設定したときに機能させることができました(そして、ビューへの直接参照を使用してモデルビューでの最初の試みで あえぎ!)

しかし、私が遭遇した最初の問題は、コードの背後や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メソッドが呼び出されるまでに、自動ろ過のコレクションがすでに変更されているため、ハンドラーを効果的に外すことはできません。

私はこれを仮定するのに正しいですか?そして、誰もがこれらのハンドラーを管理するより良い方法を考えると、拡張クラス内でその機能をカプセル化することを可能にしますか?

投稿の長さについて申し訳ありませんが、助けてくれてありがとう!

- ファンガー

役に立ちましたか?

解決

その時点でオートフィルターバリューがすでに変更されていることは正しいので、間違ったハンドラーを見て、メモリリークが発生します。

ソリューションは非常に簡単です。あなたがしていることを正確に行いますが、使用してください List<IList> AutoFilterValuesを参照するだけでなく、

private List<IList> _GridFilters;

そして使用します ToList() フィルターのコピーを作成するには、ハンドラーを設定します。

_GridFilters = dataGridCollectionView.AutoFilterValues.Values.ToList();

_gridfiltersは現在aです List<IList>, 、ループも変更する必要があります。

foreach(IList autofilterValues in _GridFilters) 
  ...

これが機能する理由は、古いフィルターリストの実際のリストが、AutoFilterValuesプロパティを単に参照するのではなく、_gridFiltersにコピーされるためです。

これは、多くの状況で適用可能な素晴らしい一般的な手法です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top