2009-09-01 58 views
22

他の依存関係プロパティの値を使用して値が計算される依存関係プロパティはどのように登録できますか?依存関係のプロパティ依存関係

.NETプロパティラッパーは、実行時にWPFによってバイパスされるため、ゲッターとセッターにロジックを含めるべきではありません。その解決策は、通常PropertyChangedCallback秒を使用することです。しかしそれらは静的であると宣言されています。

public bool TestBool 
{ 
    get { return (bool)GetValue(TestBoolProperty); } 
    set 
    { 
    SetValue(TestBoolProperty, value); 
    TestDouble = ((value)?(100.0):(200.0)); // HERE IS THE DEPENDENCY 
    } 
} 
public static readonly DependencyProperty TestBoolProperty = 
    DependencyProperty.Register("TestBool", typeof(bool), typeof(ViewModel)); 

public double TestDouble 
{ 
    get { return ((double)GetValue(TestDoubleProperty)); } 
    set { SetValue(TestDoubleProperty, value); } 
} 
public static readonly DependencyProperty TestDoubleProperty = 
    DependencyProperty.Register("TestDouble", typeof(double), typeof(ViewModel)); 

限り、依存関係が円形でないとして、これを実現するための適切な手段があります。たとえば

、この不自然なタスクを達成するための適切な方法は何ですか?

答えて

21

Hmmm ...私はあなたが依存関係のプロパティvalue coercionをよく見るといいでしょう。ここに強制との例があります:

public class ViewModel : DependencyObject 
{ 
    public bool TestBool 
    { 
    get { return (bool)GetValue(TestBoolProperty); } 
    set { SetValue(TestBoolProperty, value); } 
    } 
    public static readonly DependencyProperty TestBoolProperty = 
    DependencyProperty.Register("TestBool", typeof(bool), typeof(ViewModel), new PropertyMetadata(false, OnTestBoolPropertyChanged)); 

    private static void OnTestBoolPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
    var vm = (ViewModel)d; 
    vm.CoerceValue(TestDoubleProperty); 
    } 

    public double TestDouble 
    { 
    get { return ((double)GetValue(TestDoubleProperty)); } 
    set { SetValue(TestDoubleProperty, value); } 
    } 
    public static readonly DependencyProperty TestDoubleProperty = 
    DependencyProperty.Register("TestDouble", typeof(double), typeof(ViewModel), new PropertyMetadata(0.0, null, OnCoerceTestDouble)); 

    private static object OnCoerceTestDouble(DependencyObject d, object baseValue) 
    { 
    var vm = (ViewModel) d; 
    var testBool = vm.TestBool; 
    return ((testBool) ? (100.0) : (200.0)); 
    } 
} 
+0

'CoerceValueCallback'を使用した場合の利点は、他の依存関係プロパティの' PropertyChangedCallback'内から依存関係プロパティをopedogのように直接変更するのはなぜですか?あなたがリンクしたドキュメントから、あなたの方がより適切な方法であることがわかりますが、実際の違いについては興味があります。 – Gregyski

+1

さて、カップルの名前を付けるには、このプロパティへのバインディングを中断しません(つまり、このプロパティがバインディング式のターゲットであれば、強制的に機能しますが、明示的に設定した後は失われます)。依存関係のプロパティ値解決の優先順位が高くなります(つまり、PropA = "Something"と言う場合、PropA == "Something"という意味ではありません。強制は無視されるため)。プロパティの古い値を覚えています(次回にCoerceValue()を呼び出すと、ローカルに設定されたものではなく、TestDoubleの元の値が取得されます) – Anvaka

1

実際には正しいですが、PropertyChangedCallbackを使用する必要があります。方法は次のとおりです。

public bool TestBool 
{ 
    get { return (bool)GetValue(TestBoolProperty); } 
    set 
    { 
    SetValue(TestBoolProperty, value); 
    } 
} 
public static readonly DependencyProperty TestBoolProperty = 
    DependencyProperty.Register("TestBool", typeof(bool), typeof(ViewModel), 
    new PropertyMetadata(false, new PropertyChangedCallback(OnTestBoolChanged))); 

private static void OnTestBoolChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    ViewModel vm = d as ViewModel; 
    vm.TestDouble = value ? 100.0 : 200.0; 
} 

public double TestDouble 
{ 
    get { return ((double)GetValue(TestDoubleProperty)); } 
    set { SetValue(TestDoubleProperty, value); } 
} 
public static readonly DependencyProperty TestDoubleProperty = 
    DependencyProperty.Register("TestDouble", typeof(double), typeof(ViewModel)); 
+0

ありがとうございますopedog。私の調査では、私は愚かに 'PropertyChangedCallback'に渡されたものを調べることに失敗しました。この方法を使用するようにテストプロジェクトを調整したところ、うまくいきました。私は次にAnvakaのソリューションを試してみるつもりです。 – Gregyski