2009-03-02 8 views
17

Gibt es Datenbindungs-Frameworks (BCL oder andere), die eine Bindung zwischen zwei CLR-Eigenschaften ermöglichen, die INotifyPropertyChanged und INotifyCollectionChanged implementieren? Es scheint zu sein, sollte es möglich sein, so etwas zu tun:Datenbindung POCO-Eigenschaften

var binding = new Binding(); 
binding.Source = someSourceObject; 
binding.SourcePath = "Customer.Name"; 
binding.Target = someTargetObject; 
binding.TargetPath = "Client.Name"; 
BindingManager.Bind(binding); 

Wo someSourceObject und someTargetObject nur POCOs sind die INotifyPropertyChanged implementieren. Allerdings ist mir keine BCL-Unterstützung dafür bekannt, und ich bin nicht sicher, ob es existierende Frameworks gibt, die dies erlauben.

UPDATE: Angesichts der Tatsache, dass keine vorhandene Bibliothek zur Verfügung steht, habe ich es auf mich genommen, meine eigene zu schreiben. Es ist verfügbar here.

Dank

Antwort

10

Ich schrieb Truss, um die Lücke zu füllen.

1

AutoMapper kann Werte zwischen zwei Instanzen kopieren, aber Sie haben Ihren eigenen Code zu schreiben, dies automatisch geschieht.

1

Vielleicht Bindable LINQ oder continuous linq kann hier helfen. Wenn Sie versuchen, Modelleigenschaften hinzuzufügen, die tatsächlich "abgeleitete Eigenschaften" Ihrer tatsächlichen Aktualisierungsdaten sind, um die Bindung Ihrer Benutzeroberfläche zu erleichtern, sollten diese beiden Frameworks hilfreich sein.

7

Ich bin keine bekannt Bibliothek, die dies tut - aber Sie könnten Ihre eigenen ziemlich einfach schreiben.

Hier ist eine Grundlage ich in wenigen Minuten oben geklopft, die Zwei-Wege-Datenbindung zwischen zwei einfachen Eigenschaften festgelegt:

public static class Binder 
{ 

    public static void Bind(
     INotifyPropertyChanged source, 
     string sourcePropertyName, 
     INotifyPropertyChanged target, 
     string targetPropertyName) 
    { 
     var sourceProperty 
      = source.GetType().GetProperty(sourcePropertyName); 
     var targetProperty 
      = target.GetType().GetProperty(targetPropertyName); 

     source.PropertyChanged += 
      (s, a) => 
      { 
       var sourceValue = sourceProperty.GetValue(source, null); 
       var targetValue = targetProperty.GetValue(target, null); 
       if (!Object.Equals(sourceValue, targetValue)) 
       { 
        targetProperty.SetValue(target, sourceValue, null); 
       } 
      }; 

     target.PropertyChanged += 
      (s, a) => 
      { 
       var sourceValue = sourceProperty.GetValue(source, null); 
       var targetValue = targetProperty.GetValue(target, null); 
       if (!Object.Equals(sourceValue, targetValue)) 
       { 
        sourceProperty.SetValue(source, targetValue, null); 
       } 
      }; 
    } 
} 

Natürlich fehlt dieser Code ein paar Nettigkeiten. Dinge hinzufügen schließen

  • Überprüfen, ob source und target
  • Überprüfen, dass die Eigenschaften identifiziert durch sourcePropertyName und targetPropertyName existieren
  • Überprüfung auf Typ Kompatibilität zwischen den beiden Eigenschaften

Auch zugeordnet sind, Spiegelung ist relativ langsam (obwohl Benchmark es vor dem Verwerfen, es ist nicht , dass langsam), so dass Sie möglicherweise kompiliert verwenden möchten Ausdrücke stattdessen.

Schließlich, da die Angabe von Eigenschaften per Zeichenfolge fehleranfällig ist, könnten Sie stattdessen Linq-Ausdrücke und Erweiterungsmethoden verwenden. Dann statt

Binder.Bind(source, "Name", target, "Name") 

schreiben könnten Sie

source.Bind(Name => target.Name); 
+0

Ich fragte tatsächlich, weil ich erwog, mein eigenes zu schreiben. Ich wollte das Rad nicht neu erfinden und alles ... danke. –

+0

Update: Ich habe in der Frage zu meiner Bibliothek verknüpft. –

+0

Ich brauchte eine einfache Barebone-Databinding-Klasse für mein aktuelles Projekt-in-Eile, und die obige passt fast zu dem, was ich brauche. Ich habe gerade die Eigenschaftsnamen, die mit Reflection verwendet werden, durch zwei Action-Delegaten ersetzt, in denen ich von der POCO-Funktion get/set und Transformationen und Formatierungen anwende. Ich werde Truss in einem nächsten Projekt definitiv einen guten Versuch geben, weil es für mich wirklich interresant klingt. – Larry

-2

schreiben Wenn Sie Ihre Eigenschaften als DependencyProperty ‚s definiert man es tun könnte. Sowohl WF als auch WPF haben eine Implementierung davon (der erste Link ist für WPF. Für WF ist es eins), also müssen Sie entscheiden, welche zu verwenden - aber beide sollten für Ihre Bedürfnisse ausreichen.

+2

DependencyProperty impliziert die Übernahme von DependencyObject, das kein POCO ist. –

+1

+1. Mit anderen Worten: "Sie können nicht mit Poco's, nur DPs." – Will

+0

Eh? Nicht sicher, was deine Logik ist, um dies zu wählen. Will. Kein Vorschlag wird für meine Bedürfnisse ausreichen, da beide Vorschläge keine POCOs beinhalten. Ein anderer Beitrag hat bereits gezeigt, dass Sie es mit POCOs tun können - ich frage nur nach einem Rahmen, der das harte Heben erledigt. –

0

Ich schrieb ein kleines Projekt Bind mit voller Unterstützung für die Bindung zwischen asested Eigenschaften Async-Bindungsaktionen. Das sintax kann nicht einfacher sein:

//Two way binding between neasted properties: 
Bind.TwoWay(()=> client.Area.Data.Name == this.AreaName); 

//On change action execute: 
Bind 
    .OnChange(()=> client.Personal.Name) 
    .Do(x => clientName = x);