2009-09-01 6 views
22

Comment enregistrer une propriété de dépendance dont la valeur est calculée à l'aide de la valeur d'une autre propriété de dépendance? Étant donné que les wrappers de propriétés .NET sont ignorés par WPF lors de l'exécution, il ne faut pas inclure de logique dans les getters et les setters. La solution à cela est généralement d'utiliser PropertyChangedCallback s. Mais ceux-ci sont déclarés statiques.Dépendance Propriété dépendante d'un autre

Par exemple, quelle est la bonne façon d'accomplir cette tâche artificielle:

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

Tant que la dépendance n'est pas circulaire, est-il un moyen approprié pour y parvenir?

Répondre

21

Hmmm ... Je pense que vous feriez mieux de regarder les propriétés de dépendance value coercion. Voici un exemple avec coercition:

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

Quel est l'avantage d'utiliser un 'CoerceValueCallback' comme vous l'avez fait par rapport à la modification directe d'une propriété de dépendance à partir de' PropertyChangedCallback' d'une autre propriété de dépendance comme opedog l'a fait? Je déduis de la documentation que vous avez liée que la vôtre est la méthode la plus appropriée, mais je suis curieux de la différence pratique. – Gregyski

+1

Eh bien, pour nommer couple: il ne casse pas les liaisons à cette propriété (c'est-à-dire si cette propriété est une cible de l'expression de liaison, elle fonctionnera après la contrainte mais sera perdue après l'ensemble explicite); il a une priorité plus élevée dans la résolution de valeur de propriété de dépendance (c'est-à-dire si vous dites PropA = "Quelque chose" qui ne signifie pas que PropA == "Quelque chose", puisque la coercition pourrait ignorer cette affectation); Il se souvient de l'ancienne valeur de votre propriété (c'est-à-dire que la prochaine fois que vous appelez CoerceValue() vous obtiendrez la valeur originale de TestDouble, pas celle qui a été définie localement) – Anvaka

1

Vous avez effectivement raison, vous devriez utiliser PropertyChangedCallback. Voici comment:

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

Merci opedog. Dans mon enquête, j'ai stupidement échoué à examiner ce qui a été passé dans 'PropertyChangedCallback'. J'ai ajusté mon projet de test pour utiliser cette méthode et cela fonctionne. Je vais essayer la solution d'Anvaka ensuite. – Gregyski

Questions connexes