2010-04-27 6 views
1

La construction XAML {Binding} est très pratique car elle gère automatiquement tous les problèmes PropertyChanged. C'est vraiment impressionnant quand vous lui donnez un chemin vers un objet, à travers des structures de données .NET, et tout est automatiquement mis à jour pour vous.Comment créer des liaisons de chemin de type XAML dans C#

Je voudrais utiliser la même chose en C#. Je voudrais avoir une propriété qui est dérivée de la valeur d'une autre propriété. Exemple

class Foo 
{ 
    public Bar Bar = new Bar(); 
    public string ItGetter 
    { 
     get 
     { 
      return Bar.Baz.It; 
     } 
    } 
} 

class Bar 
{ 
    public Baz Baz = new Baz(); 
} 

class Baz 
{ 
    public string It { get { return "You got It!"; } } 
} 

Si vous appelez ItGetter sur un Foo, vous obtenez la valeur It de Baz. Cela fonctionne bien, sauf qu'il n'est pas invalidé - c'est-à-dire, si cela a changé, il n'y aurait pas de notifications de modification sur le ItGetter. En outre, si les références Foo.Bar ou Bar.Baz sont modifiées, vous n'obtiendrez pas non plus de modifications.

Je peux ajouter le code IChangeNotify approprié sur les propriétés, mais ma question est: Comment coder la propriété ItGetter de sorte qu'elle appelle son événement PropertyChanged lorsque l'une des références dans le chemin, ou la valeur It change? J'espère que je n'ai pas à configurer manuellement la propriété a changé les événements sur tous les éléments dans le chemin ....

Merci pour toute aide!

Eric

Répondre

1

Vous pouvez jeter un oeil à dependancy properties. Ils vous permettent de définir des propriétés dans le système de propriétés WPF qui sont sauvegardées avec des piles de métadonnées et un système détaillé de résolution de valeur. Important pour vous, ils permettent qu'ils vous permettent de vous enregistrer pour les changements de propriété, et ils vous permettent de faire des valeurs dépendantes d'autres choses.

Il y a une autre bonne artcile autour, comme 'Demystifying dependency properties' by Josh Smith et 'Dependency Properties' by Christian Mosers

Vous pouvez également lire Dependency Property Callbacks and Validation

+0

Voir ma réponse (Eric), ci-dessous pour le code complet de cette solution. – Eric

1

Voici le code complet qui fait ce que je cherchais, en utilisant des propriétés de dépendance, comme Simon mentionné:

// This class exists to encapsulate the INotifyPropertyChanged requirements 
public class ChangeNotifyBase : DependencyObject, INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    } 
} 

public class Foo : ChangeNotifyBase 
{ 
    public Foo() 
    { 
     Bar = new Bar(); 
     var binding = new Binding("Bar.Baz.It"); 
     binding.Source = this; 
     binding.Mode = BindingMode.TwoWay; 
     BindingOperations.SetBinding(this, ItGetterProperty, binding); 
    } 

    /// <summary> 
    /// The ItGetter dependency property. 
    /// </summary> 
    public bool ItGetter 
    { 
     get { return (bool)GetValue(ItGetterProperty); } 
     set { SetValue(ItGetterProperty, value); } 
    } 
    public static readonly DependencyProperty ItGetterProperty = 
     DependencyProperty.Register("ItGetter", typeof(bool), typeof(Foo)); 

    // Must do the OnPropertyChanged to notify the dependency machinery of changes. 
    private Bar _bar; 
    public Bar Bar { get { return _bar; } set { _bar = value; OnPropertyChanged("Bar"); } } 
} 

public class Bar : ChangeNotifyBase 
{ 
    public Bar() 
    { 
     Baz = new Baz(); 
    } 
    private Baz _baz; 
    public Baz Baz { get { return _baz; } set { _baz = value; OnPropertyChanged("Baz"); } } 
} 

public class Baz : ChangeNotifyBase 
{ 
    private bool _it; 
    public bool It { get { return _it; } set { _it = value; OnPropertyChanged("It"); } } 
} 

Si vous vous inscrivez dès maintenant pour les événements sur ItGetter, vous serez informé si l'une de ces choses changent: Baz.It Foo.Bar (par exemple, changer la référence) Bar.Baz ""

Si vous définissez sur des références d'objet (foo.bar ou Bar.Baz) à null, la valeur de ItGetter change false.

+0

Nice un Eric +1. C'est génial de voir quelqu'un qui a pris le temps de revenir et de contribuer à ses résultats. C'est vraiment dans l'esprit de SO, Merci. –