2009-09-01 15 views
22

Jak można zarejestrować właściwość zależności, której wartość jest obliczana przy użyciu wartości innej właściwości zależności?Właściwość zależności zależna od innej

Ponieważ opakowania programu .NET są pomijane przez WPF w czasie wykonywania, nie należy uwzględniać logiki w programach pobierających i ustawiających. Rozwiązaniem tego jest zwykle użycie s. PropertyChangedCallback. Ale są one uznawane za statyczne.

Na przykład, co jest właściwą drogą do osiągnięcia tego contrived zadanie:

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

Dopóki zależność nie jest okrągła, czy istnieje odpowiednie środki, aby osiągnąć ten cel?

Odpowiedz

21

Hmmm ... Chyba lepiej spojrzeć na właściwości uzależniających value coercion. Oto przykład z przymusem:

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

Jaka jest zaleta korzystania z 'CoerceValueCallback' w porównaniu z bezpośrednią zmianą właściwości zależności w ramach właściwości PropertyChangedCallback innego obiektu zależnego, jak zrobił to opedog? Ze zgromadzonej przeze mnie dokumentacji wynika, że ​​twoja metoda jest bardziej właściwa, ale jestem ciekawa praktycznej różnicy. – Gregyski

+1

Cóż, aby nazwać parę: nie rozbija powiązań z tą właściwością (tj. Jeśli ta właściwość jest celem wyrażenia wiążącego, będzie działać po wymuszeniu, ale zostanie utracona po jawnym ustawieniu); ma wyższy priorytet w rozwiązywaniu wartości właściwości zależności (tzn. jeśli mówisz PropA = "Coś", co nie oznacza, że ​​PropA == "Coś", ponieważ przymus może zignorować to przypisanie); Zapamiętuje starą wartość twojej własności (tj. Następnym razem, gdy wywołasz CoerceValue(), otrzymasz oryginalną wartość TestDouble, a nie tę ustawioną lokalnie) – Anvaka

1

Właściwie masz rację, powinieneś użyć PropertyChangedCallback. Oto jak:

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

Dziękuję opedog. W moim dochodzeniu nierozsądnie nie sprawdzałem, co zostało przekazane do 'PropertyChangedCallback'. Poprawiłem swój projekt testowy, aby korzystać z tej metody i działa. Mam zamiar wypróbować rozwiązanie Anvaki. – Gregyski

Powiązane problemy