2012-10-18 5 views
5

Ich beabsichtige Datenbindung zwischen einigen meiner Klassen zu verwenden. Mit anderen Worten, ich verbinde keine Werte zwischen einer Modellklasse und der UI, sondern binde Variablen zwischen verschiedenen Klassen.Wie kann ich im Code mit C# Daten binden?

Ich habe über Datenbindung in C# an mehreren Stellen gelesen, aber die meisten von ihnen beziehen sich auf die Bindung zwischen Windows Form und einem Quellobjekt.

Ich bin noch neu in C#. Dies ist, wie ich verstehe, was ich tun sollte:

Erstens, für meine Quellobjekt, hat eine Klassenname von DataObject. Das Quellobjekt muss eine INotifyPropertyChange-Schnittstelle implementieren und dann das Ereignis auslösen, wenn die Eigenschaft health auf "Ändern" gesetzt ist. Ich habe damit kein Problem.

Angenommen, ich habe ein Zielobjekt namens CharacterClass. life ist eine Eigenschaft in CharacterClass und ist auch die Zieleigenschaft, die an die Eigenschaft health des Quellobjekts gebunden werden soll.

Wie kann ich die beiden Eigenschaften (sowohl unidirektional als auch bidirektional) im Code nur mit dem normalen .NET-Framework verbinden?

Ein wenig Hintergrundinformationen darüber, warum ich diese Frage stellen:

Gerade falls Sie denken, dies auf eine erneute Frage ist, ist es nicht. Ich habe durch SE gesucht. Die anderen Fragen zur Datenbindung in Code sind im Kontext von WPF oder XAML, was nicht für mich ist. Ich habe auch mehrere Artikel auf MSDN gelesen und es scheint, dass ich ein Binding Objekt erstellen und dann die Quelle und das Ziel über BindingOperations.SetBinding() binden konnte. Die Klasse Binding scheint jedoch Teil der WPF-Bibliothek unter dem Namespace System.Windows.Data.Binding zu sein. Obwohl ich C# verwende, bezweifle ich, dass ich den Luxus hätte, auf WPF-Bibliotheken zuzugreifen, weil ich hauptsächlich C# als einzige Skriptsprache in Unity3D verwende. Ich glaube, ich habe nur Zugang zum vanilla.Net Framework. Aber ich bin mir da nicht ganz sicher, weil ich noch neu in C# bin.

Antwort

7

Obwohl es eine starke Unterstützung für Bindungen gibt, die eng mit dem verwendeten UI-Framework verbunden ist, können Sie dennoch problemlos Ihr eigenes Bindungsframework schreiben.

Hier ist ein POC, der eine unidirektionale Bindung zwischen Eigenschaften von zwei Objekten implementiert.

Hinweis: Dies ist nur einer der möglichen Wege, ein POC bestenfalls (Feinabstimmung für hohe Leistung/Produktionsszenario) und .Net 2.0 Klassen und Schnittstellen ohne Abhängigkeit von einem UI-Framework verwendet Vanille '.net Rahmen in deinen Wörtern :)).als auch die Bindung

class Program 
{ 
    public static void Main() 
    { 
     Source src = new Source(); 
     Destination dst = new Destination(src); 
     dst.Name = "Destination"; 
     dst.MyValue = -100; 
     src.Value = 50; //changes MyValue as well 
     src.Value = 45; //changes MyValue as well 
     Console.ReadLine(); 
    } 
} 

//A way to provide source property to destination property 
//mapping to the binding engine. Any other way can be used as well 
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
internal class BindToAttribute : Attribute 
{ 
    public string PropertyName 
    { 
     get; 
     private set; 
    } 

    //Allows binding of different properties to different sources 
    public int SourceId 
    { 
     get; 
     private set; 
    } 

    public BindToAttribute(string propertyName, int sourceId) 
    { 
     PropertyName = propertyName; 
     SourceId = sourceId; 
    } 
} 

//INotifyPropertyChanged, so that binding engine knows when source gets updated 
internal class Source : INotifyPropertyChanged 
{ 
    private int _value; 
    public int Value 
    { 
     get 
     { 
      return _value; 
     } 
     set 
     { 
      if (_value != value) 
      { 
       _value = value; 
       Console.WriteLine("Value is now: " + _value); 
       OnPropertyChanged("Value"); 
      } 
     } 
    } 

    void OnPropertyChanged(string propertyName) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

internal class Destination 
{ 
    private BindingEngine<Destination> _binder; 

    private int _myValue; 

    [BindTo("Value", 1)] 
    public int MyValue 
    { 
     get 
     { 
      return _myValue; 
     } 
     set 
     { 
      _myValue = value; 
      Console.WriteLine("My Value is now: " + _myValue); 
     } 
    } 

    //No mapping defined for this property, hence it is not bound 
    private string _name; 
    public string Name 
    { 
     get 
     { 
      return _name; 
     } 
     set 
     { 
      _name = value; 
      Console.WriteLine("Name is now: " + _name); 
     } 
    } 

    public Destination(Source src) 
    { 
     //Binder for Source no 1 
     _binder = new BindingEngine<Destination>(this, src, 1); 
    } 
} 

internal class BindingEngine<T> 
{ 
    private readonly T _destination; 
    private readonly PropertyDescriptorCollection _sourceProperties; 
    private readonly Dictionary<string, PropertyDescriptor> _srcToDestMapping; 

    public BindingEngine(T destination, INotifyPropertyChanged source, int srcId) 
    { 
     _destination = destination; 

     //Get a list of destination properties 
     PropertyDescriptorCollection destinationProperties = TypeDescriptor.GetProperties(destination); 

     //Get a list of source properties 
     _sourceProperties = TypeDescriptor.GetProperties(source); 

     //This is the source property to destination property mapping 
     _srcToDestMapping = new Dictionary<string, PropertyDescriptor>(); 

     //listen for INotifyPropertyChanged event on the source 
     source.PropertyChanged += SourcePropertyChanged; 

     foreach (PropertyDescriptor property in destinationProperties) 
     { 
      //Prepare the mapping. 
      //Add those properties for which binding has been defined 
      var attribute = (BindToAttribute)property.Attributes[typeof(BindToAttribute)]; 
      if (attribute != null && attribute.SourceId == srcId) 
      { 
       _srcToDestMapping[attribute.PropertyName] = property; 
      } 
     } 
    } 

    void SourcePropertyChanged(object sender, PropertyChangedEventArgs args) 
    { 
     if (_srcToDestMapping.ContainsKey(args.PropertyName)) 
     { 
      //Get the destination property from mapping and update it 
      _srcToDestMapping[args.PropertyName].SetValue(_destination, _sourceProperties[args.PropertyName].GetValue(sender)); 
     } 
    } 
} 

enter image description here

0

Ich glaube, ich nur Zugriff auf das

Die Realität des Vanille-Net Framework ist, dass Daten in UI verwendet Bindung. Wenn jemand über die Datenbindung spricht, impliziert er automatisch "Datenbindung in [UI-Framework-Name]".

Sie können Objekt-Objekt-Zuordnung statt Datenbindung berücksichtigen.

+0

Eigentlich ja, Sie haben Recht, über die Datenbindung Befinden für UI Sobald Sie dies verstanden haben, können Sie einfach diese erweitern 2-Wege zu unterstützen. In meiner Situation baue ich eine Benutzeroberfläche, aber nicht mit dem Windows Form. Und all diese * Zielobjekte *, auf die ich mich bezog, sind hauptsächlich meine UI-Klassen. Also, was ich hoffe, ist für eine "Gewohnheit" der Art Datenbindungstechnik, die ich auf meiner eigenen Nicht-WinForm UI implementieren könnte. – Carven

+0

@xEnOn: Das Hauptproblem ist, dass Binding-Engines eng mit UI-Framework-Interna verbunden sind. Zum Beispiel verwendet die WPF-Bindung Abhängigkeitseigenschaften. Wenn Sie diese also verwenden möchten, müssen Sie Ihre UI-Klassen so schreiben, dass sie 'DependencyObject'-Nachkommen sind. Ich denke, du solltest deine eigene verbindliche Engine schreiben. – Dennis

+0

Ich verstehe. Vielen Dank! Sieht so aus, als hätte ich kein Glück, C# 's Datenbindungsmodul zu verwenden. :(Ich denke, ich muss herausfinden, wie ich meine eigene Binding-Engine schreiben kann. Vielleicht werde ich hier eine neue Frage stellen, um zu verstehen, wie Datenbindungs-Engines unter der Haube funktionieren, um mir eine Idee zu geben, wie ich eine Datenbindung schreiben kann Vielen Dank, Dennis :) – Carven

Verwandte Themen