2009-03-02 13 views
17

Esistono strutture di associazione dati (BCL o altro) che consentono il collegamento tra di due proprietà CLR che implementano INotifyPropertyChanged e INotifyCollectionChanged? Sembra essere dovrebbe essere possibile fare qualcosa del genere:Proprietà POCO di binding dati

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

Dove someSourceObject e someTargetObject sono solo pocos che implementano INotifyPropertyChanged. Tuttavia, non sono a conoscenza di alcun supporto BCL per questo e non sono sicuro che esistano framework che lo consentano.

UPDATE: Dato che non esiste una libreria disponibile, ho deciso di scrivere da sola. È disponibile here.

Grazie

risposta

10

Ho scritto Truss per riempire il vuoto.

1

AutoMapper possono copiare i valori tra due istanze, ma è necessario scrivere il proprio codice per fare questo accadere automaticamente.

1

Forse Bindable LINQ o continuous linq può aiutare qui. Se stai cercando di aggiungere proprietà del modello che sono in realtà "proprietà derivate" dei tuoi dati effettivi e di aggiornamento, per rendere più facile l'interfaccia utente all'interfaccia utente, questi due framework dovrebbero aiutare.

7

Non sono a conoscenza di nessuna libreria , ma è possibile scrivere la propria abbastanza facilmente.

Ecco una base Ho bussato in pochi minuti che stabilisce due dati modo vincolante tra due proprietà semplici:

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

Naturalmente, questo codice manca un paio di sottigliezze. Cose da aggiungere sono

  • Verifica che source e target sono assegnati
  • Verifica che le proprietà identificate da sourcePropertyName e targetPropertyName esistono
  • Verifica per digitare la compatibilità tra le due proprietà

Inoltre, Riflessione è relativamente lento (benchmark prima di scartarlo, non è che lento), quindi potresti voler usare compilato espressioni invece.

Infine, dato che la specificazione delle proprietà per stringa è soggetta a errore, è possibile utilizzare invece espressioni di Linq e metodi di estensione. Poi invece di scrivere

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

si potrebbe scrivere

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

realtà stavo chiedendo perché mi stava prendendo in considerazione scrivere il mio. Non volevo reinventare la ruota e tutto ... grazie. Aggiornamento –

+0

: ho collegato alla mia biblioteca nella domanda. –

+0

Avevo bisogno di una semplice classe di calcolo dati barebone per il mio progetto corrente-in-a-hurry, e quello sopra quasi si adatta a ciò di cui ho bisogno. Ho appena sostituito i nomi di proprietà usati con Reflection da due delegati di Action in cui ottengo/set dal POCO e applico le trasformazioni e la formattazione. Darò sicuramente una buona prova a Truss in un prossimo progetto, perché suona davvero molto interessante per me. – Larry

-2

Se è stato definito le proprietà come DependencyProperty 's si potesse fare. Sia WF che WPF ne hanno un'implementazione (il primo collegamento è per WPF. Per WF è this uno) quindi è necessario decidere quale utilizzare, ma entrambi dovrebbero essere sufficienti per le proprie esigenze.

+2

DependencyProperty implica l'ereditarietà da DependencyObject, che non è un POCO. –

+1

+1. In altre parole, "Non puoi con poco, solo DP". – Will

+0

Eh? Non sei sicuro di quale sia la tua logica per votare su questo Will. Nessuno dei due suggerimenti sarà sufficiente per i miei bisogni in quanto nessuno dei due suggerimenti riguarda i POCO. Un altro post ha già dimostrato che puoi farlo con POCO: sto solo chiedendo un framework che faccia il duro lavoro. –

0

Ho scritto un piccolo progetto Bind con il supporto completo per il binding tra le azioni di associazione asincrona di proprietà neasted. La sintassi non può essere più semplice:

//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); 
Problemi correlati