2009-09-01 19 views
22

Wie kann man eine Abhängigkeitseigenschaft registrieren, deren Wert mit dem Wert einer anderen Abhängigkeitseigenschaft berechnet wird?Abhängigkeitseigenschaft abhängig von einer anderen

Da die .NET-Eigenschaftenwrapper zur Laufzeit von WPF umgangen werden, sollte keine Logik in die Getter und Setter einbezogen werden. Die Lösung dafür ist typischerweise PropertyChangedCallback s zu verwenden. Aber diese werden als statisch deklariert.

Zum Beispiel, was ist der richtige Weg, diese erfundene Aufgabe zu erfüllen:

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)); 

Solange die Abhängigkeit nicht kreisförmig ist, ist es ein geeignetes Mittel, um dies zu erreichen?

Antwort

21

Hmmm ... Ich glaube, Sie sollten besser sehen Abhängigkeitseigenschaften value coercion. Hier ist ein Beispiel mit Zwang:

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

Was ist der Vorteil der Verwendung eines 'CoerceValueCallback's, wie Sie es getan haben, im Vergleich zu einer direkten Änderung einer Abhängigkeitseigenschaft aus einer anderen Abhängigkeitseigenschaft' PropertyChangedCallback', wie es opedog getan hat? Ich entnehme der Dokumentation, die Sie verlinkt haben, dass Ihre Methode die geeignetere ist, aber ich bin neugierig auf den praktischen Unterschied. – Gregyski

+1

Nun, um ein paar zu nennen: Es bricht die Bindungen zu dieser Eigenschaft nicht (d. H. Wenn diese Eigenschaft ein Ziel des Bindungsausdrucks ist, wird sie nach der Zwangsführung funktionieren, wird aber nach der expliziten Festlegung verloren gehen); es hat eine höhere Priorität bei der Auflösung von Abhängigkeitseigenschaftswerten (d. h., wenn Sie PropA = "Etwas" sagen, was nicht bedeutet, dass PropA == "Etwas" ist, da die Zwangsumsetzung diese Zuweisung ignorieren könnte); Es merkt sich den alten Wert Ihrer Eigenschaft (d. H. Beim nächsten Aufruf von CoerceValue() erhalten Sie den ursprünglichen Wert von TestDouble, nicht den, der lokal gesetzt wurde) – Anvaka

1

Sie sind eigentlich richtig, sollten Sie PropertyChangedCallback verwenden. Hier ist, wie:

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

Danke opedog. In meiner Untersuchung habe ich es törichterweise versäumt, zu untersuchen, was in den "PropertyChangedCallback" übertragen wurde. Ich habe mein Testprojekt angepasst, um diese Methode zu verwenden, und es funktioniert. Ich werde als nächstes Anvakas Lösung versuchen. – Gregyski

Verwandte Themen