2017-05-01 2 views
2

Angenommen, Sie haben ein Objekt mit einer Eigenschaft, an die Sie ein Steuerelement binden. Wie folgt aus:Bindung an die Referenz, nicht an das Objekt

MyClass MyObject = new MyClass(); 
MyObject.MyProperty = "Hello StackOverflow!"; 
MyTextBox.DataBindings.Add("Text", MyObject, nameOf(MyObject.MyProperty); 

Und Sie dann ändern MyObject auf eine neue Instanz von MyClass, wie folgt aus:

MyObject = new MyClass(); 
MyObject.MyProperty = "I've made a new instance of my class..."; 

Dann MyTextBox wird noch auf die Instanz von MyClass gebunden werden, wo MyProperty ist auf " Hallo StackOverflow! ". Gibt es die Datenbindungen trotzdem so festzulegen, dass sie bei der neuen Instanz der Klasse bleiben? Ich weiß, dass ich die DataBindings einfach wieder setzen kann, aber manchmal ist das nicht so einfach wie in diesem Beispiel.

+1

Nein. Sie binden ein Objekt, nicht den Variablennamen. –

+1

Ja, bind an eine Eigenschaft deines Viewmodels. Machen Sie Ihr Viewmodel zur Quelle der Bindung und geben Sie einen Pfad zur Eigenschaft an. Stellen Sie sicher, dass Ihr Ansichtsmodel INotifyPropertyChanged ordnungsgemäß gepulst hat. –

Antwort

0

Datenbindungen unterstützen Eigenschaftenpfade für die Quelleneigenschaft. Solange Sie also Ihre MyObject-Variable in ein anderes Objekt einfügen, das für die Datenbindung verwendet werden kann, können Sie den Eigenschaftennamen angeben, der auf die Eigenschaft verweist, die diesen Wert enthält, dann einen Punkt und dann die tatsächlich gewünschte Eigenschaft .

Zum Beispiel nehmen wir an, Sie haben eine Model-Klasse mit einem MyClass Eigenschaftswert: (. Die oben nimmt sie eine Hilfsmethode _UpdateField(), die das Feld behandelt die Aktualisierung und die Erhöhung der PropertyChanged Ereignis als notwendig)

class Model : INotifyPropertyChanged 
{ 
    private MyClass _myClass; 
    public MyClass MyClass 
    { 
     get { return _myClass; } 
     set { _UpdateField(ref _myClass, value); } 
    } 
} 

Dann können Sie Ihre Bindung wie so definieren:

Model model = new Model(); // initialized somewhere you can access this reference later 
model.MyClass.MyProperty = "Hello StackOverflow!"; 
MyTextBox.DataBindings.Add("Text", model, 
    nameof(Model.MyClass) + "." + nameof(MyClass.MyProperty); 

Dann, wenn Sie Möchten Sie das Objekt MyClass aktualisieren, ändern Sie den Eigenschaftswert model.MyClass. Die Bindung aktualisiert den Zielwert entsprechend.


Hier ist ein komplettes Beispiel (mit Ausnahme der * .Designer.cs Datei & hellip; nur sicherstellen, dass es eine Label und Button auf dem Formular ist, mit ihren Standardnamen und abonnieren den Button.Click Ereignis an den Handler im Code unten):

public partial class Form1 : Form 
{ 
    private readonly C2[] _rgc2 = 
    { 
     new C2 { Text = "First C2" }, 
     new C2 { Text = "Second C2" }, 
    }; 

    private readonly C1 _c1 = new C1(); 

    private bool _toggle = false; 

    public Form1() 
    { 
     InitializeComponent(); 
     label1.DataBindings.Add("Text", _c1, nameof(C1.C2) + "." + nameof(C2.Text)); 
     _UpdateC2(); 
    } 

    private void _UpdateC2() 
    { 
     _c1.C2 = _rgc2[_toggle ? 1 : 0]; 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     _toggle = !_toggle; 
     _UpdateC2(); 
    } 
} 

class C1 : NotifyPropertyChangedBase 
{ 
    private C2 _c2; 

    public C2 C2 
    { 
     get { return _c2; } 
     set { _UpdateField(ref _c2, value); } 
    } 
} 

class C2 : NotifyPropertyChangedBase 
{ 
    private string _text; 

    public string Text 
    { 
     get { return _text; } 
     set { _UpdateField(ref _text, value); } 
    } 
} 

class NotifyPropertyChangedBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void _UpdateField<T>(ref T field, T newValue, 
     Action<T> onChangedCallback = null, 
     [CallerMemberName] string propertyName = null) 
    { 
     if (EqualityComparer<T>.Default.Equals(field, newValue)) 
     { 
      return; 
     } 

     T oldValue = field; 

     field = newValue; 
     onChangedCallback?.Invoke(oldValue); 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
}