2009-09-01 173 views
22

如何注册一个依赖项属性,其值是使用另一个依赖项属性的值计算的?依赖属性依赖于另一个

因为.NET属性包装在运行时被WPF绕过,所以不应该在getter和setter中包含逻辑。对此的解决方案通常使用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

嗯......我想你最好看看依赖属性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'中的依赖项属性的优点是什么?我从你链接的文档中收集到你的是更合适的方法,但我对实际的区别很好奇。 – Gregyski 2009-09-01 22:03:36

+1

那么,为了名字夫妇:它不打破绑定到这个属性(即如果这个属性是绑定表达的目标,它会在强制之后工作,但会在显式设置后丢失);它在依赖属性值解析中具有更高的优先级(即,如果你说PropA =“Something”并不意味着PropA ==“Something”,因为强制可以忽略该赋值);它记住你的财产的旧值(即下次调用CoerceValue()时,你将得到TestDouble的原始值,而不是本地设置的值) – Anvaka 2009-09-01 22:38:02

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 2009-09-01 22:18:21