4

依存関係プロパティ「IsLightOnVal」を持つコントロールがあり、魔女は次のように定義されています。

// List of available states for this control
private ObservableCollection<CtlStateBool> m_IsLightOnVal;

[Category("Properties")]
public System.Collections.ObjectModel.ObservableCollection<CtlStateBool> IsLightOnVal
{
    get
    {
        if (m_IsLightOnVal == null)
            m_IsLightOnVal = new System.Collections.ObjectModel.ObservableCollection<CtlStateBool>();
        return m_IsLightOnVal;
    }
    set
    {
        if (m_IsLightOnVal != value)
        {
            m_IsLightOnVal = value;
            OnPropertyChanged("IsLightOnVal");
        }
    }
}

// IsLightOnVal dependency property.
public static readonly DependencyProperty IsLightOnValProperty =
        DependencyProperty.Register("IsLightOnVal", typeof(System.Collections.ObjectModel.ObservableCollection<CtlStateBool>), typeof(ButtonSimple), new UIPropertyMetadata(new System.Collections.ObjectModel.ObservableCollection<CtlStateBool>()));

私のコレクションでは、各要素に文字列 (状態) とブール値 (値) が含まれています。

コントロールのスタイルは ControlTemplate で定義されています。

たとえば、コレクションの最初の要素が true の場合にトリガーを追加して、何かを実行したいと考えています。

私はこれを試しました:

<Style x:Key="Btn_RADIO_VHF" TargetType="{x:Type ButtonSimple}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type ButtonSimple}">
            <Canvas .../>
            <ControlTemplate.Triggers>
               <DataTrigger Value="True" Binding="{Binding IsLightOnVal[0].Value, RelativeSource={RelativeSource TemplatedParent}}">
                  <Setter Property="Fill" TargetName="pShowTouch" Value="{DynamicResource ShowTouch}"/>
               </DataTrigger>
            </ControlTemplate.Triggers>

DataTrigger の代わりに単純な Trigger も試してみましたが、バインディングをサポートしていないようです...

誰かが私を助けることができますか?

4

3 に答える 3

4

現在、ObservableCollection含まれている要素のプロパティ変更通知をサポートしていないため、トリガーがトリガーされることはありません。

ObservableCollectionの拡張ObservableCollectionなど、ここに示すように、ChangeNotificationをサポートする特殊化を実装してみることができます。

ただし、最初の値をObservableCollectionViewModel /コードの背後に保存し、それをトリガーのターゲットとして設定する方が簡単な場合があります。

于 2012-07-23T14:38:29.700 に答える
4

そこには多くの問題があります。まず、TemplatedParentのRelativeSourceを使用していますが、これはテンプレート内の要素に適用されるバインディングではないため、Selfを使用する必要があります。したがって、比較的簡単に修正できます。

<DataTrigger Value="True" Binding="{Binding Path=IsLightOnVal[0].Value, RelativeSource={RelativeSource Self}}">

次に、このプロパティを CLR プロパティ (独自のバッキング ストアを持つ) と DependencyProperty の両方として定義しました。プロパティが DP として定義されている場合、フレームワークは、DP を使用して値を格納することを期待します。コードでは、SetValue メソッドを使用してコレクション インスタンスを DependencyObject のバッキング ストアに実際に格納することはありません。したがって、これを修正するにはいくつかの方法があります。

1) DP を削除します。

//public static readonly DependencyProperty IsLightOnValProperty =
//        DependencyProperty.Register( "IsLightOnVal", typeof( System.Collections.ObjectModel.ObservableCollection<CtlStateBool> ), typeof( ButtonSimple ), new UIPropertyMetadata( new System.Collections.ObjectModel.ObservableCollection<CtlStateBool>() ) );

セッターで設定することはできませんが、DP ではないため、VM のプロパティにバインドするなど、これはおそらく最適なオプションではありません。

2) DP とローカル変数に値を格納します。

public System.Collections.ObjectModel.ObservableCollection<CtlStateBool> IsLightOnVal
{
    get
    {
        if ( m_IsLightOnVal == null )
            this.SetValue(IsLightOnValProperty, m_IsLightOnVal = new System.Collections.ObjectModel.ObservableCollection<CtlStateBool>());
        return m_IsLightOnVal;
    }
    set
    {
        if ( m_IsLightOnVal != value )
        {
            this.SetValue( IsLightOnValProperty, m_IsLightOnVal = value );
            OnPropertyChanged( "IsLightOnVal" );
        }
    }
}

私は個人的にこのオプションが好きではありません。または、より具体的には、ゲッターで独自のプロパティを遅延して割り当てるのは悪い習慣だと思います。これにより、オブジェクトにローカル値が設定され、誰かが実際に低い優先順位で値を設定した場合 (たとえば、このインスタンスがテンプレートで定義され、そこでプロパティが設定/バインドされた場合)、実際の値が上書きされる可能性があります。また、設計時のサポートを計画している場合、これは設計者を台無しにする可能性があります。このルートに進む場合は、実際には DP 定義に PropertyChangedHandler を追加し、そこに m_IsLightOnVal メンバー変数を設定する必要があります。そうしないと、値が DP を介して設定されている場合 (たとえば、誰か - を含む) WPF フレームワーク - SetValue を使用してプロパティの値を設定します)。

3) GetValue/SetValue のみを使用する

public System.Collections.ObjectModel.ObservableCollection<CtlStateBool> IsLightOnVal
{
    get { return (System.Collections.ObjectModel.ObservableCollection<CtlStateBool>)this.GetValue(IsLightOnValProperty); }
    set { this.SetValue( IsLightOnValProperty, value ); }
}

このアプローチをお勧めします。はい、プロパティを設定したい人は誰でもコレクションのインスタンスを定義する必要があることを意味しますが、これは、独自の DP 値を設定した場合に発生する可能性のある種類の問題よりも好ましいと思います。このルートを使用する場合、ObservableCollection から派生する非ジェネリック コレクション クラスを定義して、誰かが xaml でコレクション クラスのインスタンスを定義できるようにすることをお勧めします。問題ではないかもしれません。xamlで設定されているように聞こえますが、他の返信のコメントから。

于 2012-10-23T17:12:34.327 に答える