0

ObservableCollectionSilverlight および WPF アプリの場合、依存関係プロパティとしてを含むカスタム コントロールがあります。そのコントロールの 1 つの要素である Border は、 内の項目の構成に応じて色を変更する必要がありますObservableCollection

たとえば、コレクションが動物、野菜、鉱物であり、ObjectList. 少なくとも 1 匹の動物がいる場合は、境界線を赤くします。動物がなく、野菜が少なくとも 1 つある場合は緑色です。それ以外の場合、コレクションには鉱物しか含まれていないため、青色で表示されます。

コレクションを取得して色を決定できるコンバーターを作成したので、次のようなバインディングを作成します。

<Border Background="{Binding ObjectList, 
                     RelativeSource={RelativeSource Self}, 
                     Converter={StaticResource MyColorConverter}}" />

課題は、アイテムが追加/削除されるObjectListと、背景色の再評価をトリガーする必要があることです。ただし、ObjectListそれ自体は変わりません。3 つのオプションがあると思いますが、どれがベスト プラクティスであるかはわかりません。

  1. オブジェクトが追加または削除されるたびに、新しいコレクションを作成します。これは手間がかかるように見えますが、結果ObjectListとして変更されるため、バックグラウンド更新がトリガーされます。

  2. のコールバックでUpdateTargetbackground プロパティを呼び出します。Silverlight では使用できないため、バインドを削除して再度追加するだけです。これもまた少し面倒です。CollectionChangedObjectListUpdateTarget

  3. INotifyPropertyChangedカスタム コントロールに実装PropertyChangedObjectList、実装内で呼び出しますCollectionChanged

私は 3 が一番好きですが、INPC も実装する DependencyObject があるという事実は奇妙に思えます。それは...ですか?よりエレガントなアプローチはありますか?

4

1 に答える 1

2

MSDN のドキュメントで推奨されている方法があります ( VisualStateManager を操作するためのベスト プラクティスまでスクロールします。完全な .Net 用に書かれていますが、このセクションは Silverlight にも適しています)。VisualStatesカスタムのプロパティ/状態に依存する場合は常に、ControlVisualState に影響するプロパティごとに ChangedHandler を用意しUpdateVisualStates、そこからプライベート メソッドを呼び出すことをお勧めします。条件を評価し、VisualStatesこのメソッド内からプログラムで設定します。

VisualStates色の変更に使用していない場合でも、この同じパターンに従うことをお勧めします.

次のコードは、簡潔にするために不完全なままになっています。

public ObservableCollection ObjectList {...}
public static readonly DependencyProperty ObjectListProperty =
    DependencyProperty.Register(...OnObjectListChanged...);

private static void OnObjectListChanged(...)
{ObjectList.CollectionChanged += OnObjectListCollectionChanged;}

private void OnObjectListCollectionChanged(...){ UpdateVisualStates(); }

private void UpdateVisualStates()
{
    //actually you have to instatiate a SolidColorBrush here
    if (ContainsAtLeastOneAnimal()) { m_border.Background = Colors.Red; }
    else if (ContainsAtLeastOneVegetable()) {m_border.Background = Colors.Green;}
    else { m_border.Background = Colors.Blue; }
}

ボーダーへの参照が必要ない場合は、自由に DependencyProperty BorderColorを導入し、xaml からそれにバインドしてください。大丈夫だよ。そして、別の可動部分があっても本当に問題はありません。これは、ObjectList インスタンス全体が変更されたことをシミュレートするよりもはるかに優れています。

于 2014-06-10T09:35:46.740 に答える