18

検索拡張機能を使用してカスタムWPFコントロールを作成しました。名前を付けましょうMyControl。コントロールはItemsControl クラスの子孫です。

したがって、次のようにデータソースをデータソースにフィードします。

コントロール自体は

protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
{
    if (newValue != null)
    {
        ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
        view.Filter += this.FilterPredicate;
    }

    if (oldValue != null)
    {
        ICollectionView view = CollectionViewSource.GetDefaultView(oldValue);
        view.Filter -= this.FilterPredicate;
    }

    base.OnItemsSourceChanged(oldValue, newValue);
}

ソースコレクションのビューをフィルタリングします(したがって、内部のリストボックスに表示します)。

ここで、同じDynamicSourceを使用してXAMLで定義されたこれらのMyControlが10個あるとします。問題は、それらの1つがソースコレクションにフィルターを適用すると、他のすべてのインスタンスにも影響を与えることです。

この動作を回避するために、コントロールをどのように変更しますか?

4

2 に答える 2

40

このような状況では、通常、コレクションの異なるフィルター処理の使用ごとに個別の ICollectionView インスタンスを作成する必要があります。ICollectionView の特定の実装を使用することはお勧めできません。ItemsSource が別の種類のコレクションにバインドされている場合、CollectionView の種類を変更する必要がある可能性があるためです。使用する

 ICollectionView filteredView = new CollectionViewSource { Source=newValue }.View;

正しいタイプの ICollectionView が自動的に提供されます。

残念ながら、この場合、別のコレクションをカスタム コントロールの ItemsPresenter に適用することは非常に困難です。これは、すべての魔法が基本 ItemsControl クラスによって行われ、ItemsSource/Items プロパティに依存しているためです。それは管理します。これは、ItemsControl のデフォルト テンプレートに似たものを使用した場合に発生します。

実際に ControlTemplate 内で別の ListBox コントロールを使用している場合 (および、必要に応じてすべての ItemsSource プロパティを TemplateBinding している場合)、新しい ICollectionView DP (読み取り専用をお勧めします) をコントロールに追加するだけで、コレクションのフィルタリングされたバージョンを保持し、テンプレート ListBox の ItemsSource をその新しいプロパティにバインドします。

于 2010-01-29T16:51:48.370 に答える
5

問題は、特定のソースに対してCollectionViewSource.GetDefaultView(object)常に同じICollectionViewインスタンスを返すことです。これは、ItemsControlそのソースを表示するときに拡張機能が使用するものです。

ICollectionViewこれを回避するには、コレクションを個別にフィルター処理できるようにする各コントロールで使用されるの新しいインスタンスを作成し、ItemsSource各コントロールのプロパティをその特定のビューに明示的にバインドします。必要なタイプはICollectionViewシナリオによって異なりますが、ListCollectionView一般的には適切です。

于 2010-01-29T13:40:28.000 に答える