2009-09-01 15 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

Хммм ... Я думаю, вы бы лучше взглянуть на свойства зависимостей 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 = «Что-то», это не означает, что PropA == «Что-то», поскольку принуждение может игнорировать это назначение); Он запоминает старое значение вашего свойства (т. Е. В следующий раз, когда вы вызовете 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. Я скорректировал свой тестовый проект, чтобы использовать этот метод, и он работает. Теперь я попробую решение Анваки. – Gregyski

Смежные вопросы