2009-09-01 13 views
22

¿Cómo se puede registrar una propiedad de dependencia cuyo valor se calcula utilizando el valor de otra propiedad de dependencia?Dependencia Propiedad dependiente de otra

Como WPF omite las envolturas de propiedades .NET en tiempo de ejecución, no se debe incluir la lógica en los get y setters. La solución a eso es típicamente usar PropertyChangedCallback s. Pero esos son declarados estáticos.

Por ejemplo, ¿cuál es la forma correcta de realizar esta tarea artificial:

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

Mientras que la dependencia no es circular, es que hay un medio apropiado para lograr esto?

Respuesta

21

Hmmm ... Creo que sería mejor visión de las propiedades de dependencia value coercion. Aquí hay un ejemplo con coerción:

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

¿Cuál es la ventaja de usar un 'CoerceValueCallback' como lo has hecho versus cambiar directamente una propiedad de dependencia dentro de' PropertyChangedCallback' de otra propiedad de dependencia como lo hizo opedog? De la documentación que vinculó, deduje que el suyo es el método más adecuado, pero tengo curiosidad acerca de la diferencia práctica. – Gregyski

+1

Bueno, para nombrar pareja: no rompe enlaces a esta propiedad (es decir, si esta propiedad es un objetivo de expresión de enlace, funcionará después de la coerción pero se perderá después de establecerse explícitamente); tiene mayor prioridad en la resolución de valor de propiedad de dependencia (es decir, si dices PropA = "Algo" que no significa que PropA == "Algo", ya que la coerción podría ignorar esa asignación); Recuerda el valor anterior de su propiedad (es decir, la próxima vez que llame a CoerceValue() obtendrá el valor original de TestDouble, no el que se estableció localmente) – Anvaka

1

En realidad, es correcto, debe usar PropertyChangedCallback. Así es como:

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

Gracias opedog. En mi investigación, tontamente no pude examinar lo que pasó en el 'PropertyChangedCallback'. Ajusté mi proyecto de prueba para usar este método y está funcionando. Voy a probar la solución de Anvaka a continuación. – Gregyski

Cuestiones relacionadas