Domanda

Quando si implementa ViewModel in un'applicazione WPF con architettura Model-View-ViewModel sembrano esserci due scelte principali su come renderlo indicizzabile. Ho visto implementazioni che utilizzano DependencyProperty per le proprietà a cui la vista si legherà e ho visto invece ViewModel implementare INotifyPropertyChanged .

La mia domanda è quando devo preferire l'una all'altra? Ci sono differenze di prestazioni? È davvero una buona idea assegnare le dipendenze di ViewModel a WPF? Cos'altro devo considerare quando prendere la decisione di progettazione?

È stato utile?

Soluzione

Kent ha scritto un blog interessante su questo argomento: Visualizza modelli: POCO contro DependencyObjects .

Sommario breve:

  1. DependencyObjects non sono contrassegnati come serializzabile
  2. La classe DependencyObject sovrascrive e sigilla Equals () e Metodi GetHashCode ()
  3. Un DependencyObject ha un'affinità di thread: è possibile accedervi solo sul thread su cui era creato

Preferisco l'approccio POCO. Una classe base per PresentationModel (aka ViewModel) che implementa l'interfaccia INotifyPropertyChanged è disponibile qui: http://compositeextensions.codeplex.com

Altri suggerimenti

Secondo la guida alle prestazioni di WPF, DependencyObjects ha sicuramente prestazioni migliori rispetto ai POCO che implementano INotifyPropertyChanged:

http://msdn.microsoft.com/en-us/library/ bb613546.aspx

La scelta è totalmente basata sulla logica aziendale e sul livello di astrazione dell'interfaccia utente. Se non desideri una buona separazione, DP funzionerà per te.

DependencyProperties sarà applicabile principalmente a livello di VisualElements, quindi non sarà una buona idea se creiamo molte DP per ciascuno dei nostri requisiti aziendali. Inoltre, vi è un costo maggiore per DP rispetto a INotifyPropertyChanged. Quando progetti un WPF / Silverlight prova a progettare un'interfaccia utente e ViewModel completamente separati in modo che in qualsiasi momento possiamo modificare i controlli di layout e interfaccia utente (in base al tema e agli stili)

Consulta anche questo post - https: // stackoverflow.com/questions/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel . Il collegamento ha molti riferimenti al modello Model-View-ViewModel, che è molto rilevante per questa discussione.

Da un punto di vista espressivo, mi piace molto usare le proprietà di dipendenza e rabbrividire al pensiero di INotifyPropertyChanged . Oltre ai nomi delle proprietà string e possibili perdite di memoria dovute alla sottoscrizione degli eventi, INotifyPropertyChanged è un meccanismo molto più esplicito.

Le proprietà di dipendenza implicano " in questo caso, " utilizzando metadati statici di facile comprensione. È un approccio dichiarativo che ottiene il mio voto per l'eleganza.

INotifyPropertyChanged quando utilizzato ti dà anche la possibilità di aggiungere più logica nel codice dei tuoi getter e setter delle tue proprietà.

DependencyProperty esempio:

public static DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( String), typeof( Customer ) );

public String Name
{
    set { SetValue( NameProperty, value ); }
    get { return ( String ) GetValue( NameProperty ); }
}

Nel tuo getter e setter --- tutto ciò che puoi fare è semplicemente chiamare SetValue e GetValue rispettivamente, b / c in altre parti del framework il getter / setter non viene chiamato, invece chiama direttamente SetValue, GetValue, quindi il tuo la logica di proprietà non verrebbe eseguita in modo affidabile.

Con INotifyPropertyChanged , definisci un evento:

public event PropertyChangedEventHandler PropertyChanged;

E poi semplicemente avere qualsiasi logica ovunque nel tuo codice, quindi chiama:

// ...
// Something cool...
// ...

if( this.PropertyChanged != null )
{
    PropertyChanged( this, new PropertyChangedEventArgs( "Name" ) );
}

// More cool stuff that will reliably happen...

Questo potrebbe essere in un getter / setter o in qualsiasi altro posto.

Le proprietà di dipendenza hanno lo scopo di supportare l'associazione (come destinazione) su elementi dell'interfaccia utente non come un'origine per l'associazione di dati, è qui che entra in gioco INotifyProperty. Da un punto di vista puro non si dovrebbe usare DP su ViewModels.

" Per essere l'origine di un'associazione, una proprietà non deve essere una proprietà di dipendenza; è possibile utilizzare qualsiasi proprietà CLR come fonte di associazione. Tuttavia, per essere la destinazione di un'associazione, la proprietà deve essere una proprietà di dipendenza. Perché un'associazione unidirezionale o bidirezionale sia efficace, la proprietà source deve supportare le notifiche di modifica che si propagano al sistema di associazione e quindi al target. Per le origini dell'associazione CLR personalizzate, ciò significa che la proprietà deve supportare INotifyPropertyChanged. Le raccolte dovrebbero supportare INotifyCollectionChanged. & Quot;

Non è possibile serializzare tutti gli oggetti di dipendenza (ciò potrebbe ostacolare l'uso di ViewModels e DTO (POCO).

Esistono differenze tra DP all'interno di Silverlight rispetto a WPF.

http://msdn.microsoft.com /en-us/library/cc221408(v=VS.95).aspx

http://msdn.microsoft.com/en -us / library / cc903933 (VS.95) aspx

Anch'io ho dovuto prendere in considerazione questa decisione di recente.

Ho scoperto che il meccanismo INotifyPropertyChanged si adattava meglio alle mie esigenze perché mi permetteva di incollare la mia GUI su un framework logico aziendale esistente senza duplicare lo stato. Il framework che stavo usando aveva il suo modello di osservatore ed era facile inoltrare un livello di notifica al successivo. Avevo semplicemente una classe che implementava l'interfaccia dell'osservatore dal mio framework di logica aziendale e dall'interfaccia INotifyPropertyChanged.

Con DP non è possibile definire il backend che memorizza lo stato da soli. Avrei dovuto lasciare che .net memorizzasse nella cache una copia di ogni elemento di stato a cui ero vincolante. Sembrava un sovraccarico inutile: il mio stato è ampio e complicato.

Quindi qui ho trovato INotifyPropertyChanged migliore per esporre le proprietà dalla logica di business alla GUI.

Detto questo, dove avevo bisogno di un widget della GUI personalizzato per esporre una proprietà e che le modifiche a quella proprietà influissero su altri widget della GUI DP si è rivelata la soluzione semplice.

Quindi lì ho trovato DP utile per la notifica da GUI a GUI.

  

È davvero una buona idea dare le dipendenze di ViewModel a WPF?

.NET 4.0 avrà System.Xaml.dll, quindi non dovrai prendere una dipendenza da un framework arbitrario per utilizzarlo. Vedi il post di Rob Relyea sulla sua sessione PDC.

Il mio introito

XAML è un linguaggio per la descrizione di oggetti e WPF è un framework i cui oggetti descritti sono elementi dell'interfaccia utente.

La loro relazione è simile a C #, un linguaggio per descrivere la logica, e .NET, un framework che implementa particolari tipi di logica.

Lo scopo di XAML è rappresentato da grafici di oggetti dichiarativi. Le tecnologie W * F sono ottime candidate per questo paradigma, ma XAML esiste indipendentemente da esse.

XAML e l'intero sistema di dipendenze sono stati implementati come stack separati per WF e WPF, probabilmente per sfruttare l'esperienza di diversi team senza creare una dipendenza (nessun gioco di parole previsto) tra di loro.

Le proprietà di dipendenza sono la colla della creazione del controllo personalizzato. Se si desidera utilizzare Intelli-sense per mostrare le proprietà nella finestra delle proprietà in fase di progettazione XAML, è necessario utilizzare le proprietà di dipendenza. INPC non mostrerà mai una proprietà nella finestra delle proprietà in fase di progettazione.

Sembra che le proprietà di dipendenza debbano essere usate nei controlli creati come Pulsanti. Per utilizzare le proprietà in XAML e utilizzare tutte le funzionalità di WPF, tali proprietà devono Proprietà di dipendenza.

Tuttavia, ViewModel sta meglio usando INotifyPropertyChanged. L'uso di INotifyPropertyChanged ti darà la possibilità di avere la logica getter / setter, se necessario.

Consiglio di provare la versione di Josh Smith di una classe base per un ViewModel che implementa già INotifyPropertyChanged:

http: // joshsmithonwpf. wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/

Penso che questo sia un eccellente esempio di come fare un ViewModel.

Penso che DependencyProperty e INotifyPropertyChanged siano usati per due cose diverse in Binding: il primo per consentire a una proprietà di essere una destinazione di un'associazione e ricevere l'input da un'altra proprietà (usare {Binding ...} per impostare la proprietà) , l'ultimo quando si desidera utilizzare il valore di una proprietà come origine di un'associazione (nome nell'espressione del percorso di associazione). Quindi la scelta è puramente tecnica.

Preferisco un approccio più diretto, di cui ho scritto un blog in Modello di presentazione senza INotifyPropertyChanged . Utilizzando un'alternativa all'associazione dati, è possibile associare direttamente alle proprietà CLR senza alcun codice di contabilità. Scrivi semplicemente il vecchio codice .NET nel tuo modello di visualizzazione e viene aggiornato quando cambia il tuo modello di dati.

C'è solo una cosa per preferire un DependencyObject - Il binding funzionerà meglio. Prova un esempio con ListBox e TextBox , popola l'elenco con i dati della proprietà INotifyPropertyChanged rispetto a DependencyProperty e modifica elemento corrente da TextBox ...

Se vuoi esporre le proprietà ad altri controlli devi usare le proprietà di dipendenza ... Ma buona fortuna perché impiegano un po 'di tempo per capire ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top