In MVVM il ViewModel o il modello implementano INotifyPropertyChanged?

La maggior parte degli esempi MVVM che ho elaborato hanno implementato il modello in INotifyPropertyChanged, ma nell’esempio CommandSink di Josh Smith ViewModel implementa INotifyPropertyChanged .

Sto ancora cognitivamente mettendo insieme i concetti MVVM, quindi non so se:

  • devi inserire INotifyPropertyChanged nel ViewModel per far funzionare CommandSink
  • questa è solo un’aberrazione della norma e non ha molta importanza
  • dovresti sempre avere il modello implementare INotifyPropertyChanged e questo è solo un errore che verrebbe corretto se fosse stato sviluppato da un esempio di codice a un’applicazione

Quali sono state le esperienze degli altri sui progetti MVVM su cui hai lavorato?

Direi piuttosto il contrario, ho sempre messo il mio INotifyPropertyChanged sul mio ViewModel – davvero non vuoi essere inquinante del tuo modello con una caratteristica abbastanza WPF come INotifyPropertyChanged , quella roba dovrebbe stare nel ViewModel.

Sono sicuro che gli altri non sarebbero d’accordo, ma è così che lavoro.

Sono fortemente in disaccordo con il concetto che il Modello non dovrebbe implementare l’ INotifyPropertyChanged . Questa interfaccia non è specifica per l’interfaccia utente! Semplicemente informa di un cambiamento. Infatti, WPF lo usa pesantemente per identificare i cambiamenti, ma ciò non significa che sia un’interfaccia dell’interfaccia utente. Lo paragonerei al seguente commento: ” Un pneumatico è un accessorio per auto “. Certo che lo è, ma anche biciclette, autobus, ecc. In breve, non prendere quell’interfaccia come una cosa dell’interfaccia utente.

Detto questo, non significa necessariamente che il Modello debba fornire notifiche. Di fatto, come regola generale, il modello non dovrebbe implementare questa interfaccia, a meno che non sia necessario. Nella maggior parte dei casi in cui nessun dato del server viene trasferito all’app client, il modello può essere obsoleto. Ma se si ascoltano i dati del mercato finanziario, allora non vedo perché il modello non possa implementare l’interfaccia. Ad esempio, cosa succede se ho una logica non UI come un servizio che quando riceve un prezzo Bid o Ask per un determinato valore emette un avviso (ad esempio tramite una email) o effettua un ordine? Questa potrebbe essere una ansible soluzione pulita.

Tuttavia, ci sono diversi modi per raggiungere le cose, ma vorrei sempre discutere a favore della semplicità ed evitare la ridondanza.

Cos’è meglio? Definire eventi su una collezione o modifiche di proprietà sul modello di vista e propagarlo al modello o avere la vista intrinsecamente aggiornare il modello (attraverso il modello di vista)?

La linea di fondo ogni volta che vedi qualcuno che afferma che ” non puoi fare questo o quello ” è un segno che non sanno di cosa stanno parlando.

Dipende molto dal tuo caso e in effetti MVVM è un framework con molti problemi e devo ancora vedere un’implementazione comune di MVVM su tutta la linea.

Mi piacerebbe avere più tempo per spiegare i molti gusti di MVVM e alcune soluzioni a problemi comuni, forniti principalmente da altri sviluppatori, ma suppongo che dovrò farlo un’altra volta.

In MV-VM ViewModel sempre (il modello non sempre) implementa INotifyPropertyChanged

Controlla il modello / toolkit del progetto MV-VM da http://blogs.msdn.com/llobo/archive/2009/05/01/download-mv-vm-project-template-toolkit.aspx . Usa il comando DelegateCommand e dovrebbe essere un ottimo modello di partenza per i tuoi progetti MV-VM.

Penso che MVVM abbia un nome molto basso e chiamando ViewModel un ViewModel fa in modo che molti perdersi un’importante caratteristica di un’architettura ben progettata, che è un DataController che controlla i dati indipendentemente da chi tenti di toccarli.

Se si pensa al modello di vista come a un altro DataController e si implementa un’architettura in cui il proprio DataController è l’unico elemento che tocca i dati, non si potranno mai toccare direttamente i dati, ma utilizzare sempre il DataController. DataController è utile per l’interfaccia utente ma non necessariamente solo per l’interfaccia utente. È per livello aziendale, livello dell’interfaccia utente, ecc …

 DataModel -------- DataController ------ View / Business --------/ 

Finisci con un modello come questo. Anche l’azienda dovrebbe toccare solo i dati utilizzando ViewModel. Allora il tuo enigma scompare.

Dipende da come hai implementato il tuo modello. La mia azienda utilizza oggetti aziendali simili agli oggetti CSLA di Lhotka e fa ampio uso di INotifyPropertyChanged in tutto il modello di business.

Il nostro motore di convalida si affida molto alla notifica che le proprietà cambiano attraverso questo meccanismo e funziona molto bene. Ovviamente, se si sta utilizzando una diversa implementazione diversa dagli oggetti business in cui la notifica delle modifiche non è fondamentale per l’operazione, è ansible che siano disponibili altri metodi per rilevare i cambiamenti nel modello di business.

Disponiamo inoltre di modelli di vista che propagano le modifiche dal modello laddove necessario, ma i modelli di vista stessi stanno ascoltando le modifiche del modello sottostante.

I cosa la risposta è abbastanza chiara se si desidera aderire al MV-VM.

vedere: http://msdn.microsoft.com/en-us/library/gg405484(v=PandP.40).aspx

Nel modello MVVM, la vista incapsula l’interfaccia utente e qualsiasi logica dell’interfaccia utente, il modello di visualizzazione incapsula la logica e lo stato della presentazione e il modello incapsula la logica e i dati aziendali.

“La vista interagisce con il modello di vista tramite associazione dati, comandi e modifica degli eventi di notifica.Il modello di visualizzazione esegue query, osserva e coordina gli aggiornamenti del modello, converte, convalida e aggrega i dati secondo necessità per la visualizzazione nella vista.”

Direi nel tuo ViewModel. Non fa parte del Modello in quanto il Modello è indipendente dall’interfaccia utente. Il modello dovrebbe essere “tutto ECCETTO agnostico aziendale”

Ma a volte (come in questo testo del link di presentazione) è il servizio, che fornisce l’applicazione con alcuni dati online e quindi è necessario implementare la notifica che i nuovi dati sono arrivati ​​o i dati sono cambiati usando gli eventi …

Penso che tutto dipenda dal caso d’uso.

Quando hai un modello semplice con un sacco di proprietà, puoi averlo implementando INPC. Per semplice intendo che questo modello sembra piuttosto un POCO .

Se il modello è più complesso e risiede in un dominio di modelli interattivi – modelli di riferimento modelli, sottoscrizione di eventi di altri modelli – avere eventi modello implementati come INPC è un incubo.

Mettiti in una posizione di qualche quadro modello che deve collaborare con altri modelli. Hai vari eventi a cui iscriverti. Tutti loro sono implementati come INPC. Immagina quei gestori di eventi che hai. Un’enorme cascata di clausole if e / o interruttori.

Un altro problema con INPC. Dovresti progettare le tue app per fare affidamento sull’astrazione, non sull’implementazione. Questo è tipicamente fatto usando le interfacce.

Diamo un’occhiata a 2 diverse implementazioni della stessa astrazione:

 public class ConnectionStateChangedEventArgs : EventArgs { public bool IsConnected {get;set;} } interface IConnectionManagerINPC : INotifyPropertyChanged { string Name {get;} int ConnectionsLimit {get;} /* A few more properties */ bool IsConnected {get;} } interface IConnectionManager { string Name {get;} int ConnectionsLimit {get;} /* A few more properties */ event EventHandler ConnectionStateChanged; bool IsConnected {get;} } 

Adesso guarda entrambi. Cosa ti dice IConnectionManagerINPC? Che alcune delle sue proprietà potrebbero cambiare. Non sai chi di loro. In effetti, il design è che solo IsConnected cambia, poiché il resto di essi è di sola lettura.

Al contrario, le intenzioni di IConnectionManager sono chiare: “Posso dirti che il valore della mia proprietà IsConnected può essere cambiato”.

Basta usare la proprietà INotifyPropertyChange nel tuo viewmodel e non nel Modello,

il modello di solito utilizza IDataErrorInfo per gestire gli errori di convalida, quindi tieni semplicemente ViewModel e hai ragione sulla tua strada MVVM.

Sono d’accordo con la risposta di Paulo, l’implementazione di INotifyPropertyChanged in Models è totalmente accettabile e viene anche suggerita da Microsoft –

In genere, il modello implementa le funzionalità che semplificano l’associazione alla vista. Questo di solito significa che supporta la notifica di modifica delle proprietà e delle raccolte tramite le interfacce INotifyPropertyChanged e INotifyCollectionChanged . Le classi di modelli che rappresentano raccolte di oggetti derivano in genere dalla class ObservableCollection , che fornisce un’implementazione dell’interfaccia INotifyCollectionChanged .

Anche se spetta a te decidere se vuoi quel tipo di implementazione o meno, ma ricorda –

Cosa succede se le classi del modello non implementano le interfacce richieste?

A volte è necessario lavorare con oggetti modello che non implementano le INotifyPropertyChanged , INotifyCollectionChanged , IDataErrorInfo o INotifyDataErrorInfo . In questi casi, il modello di visualizzazione potrebbe dover avvolgere gli oggetti del modello ed esporre le proprietà richieste alla vista. I valori per queste proprietà saranno forniti direttamente dagli oggetti del modello. Il modello di visualizzazione implementerà le interfacce richieste per le proprietà che espone in modo che la vista possa facilmente collegarsi ai dati.

Tratto da: http://msdn.microsoft.com/en-us/library/gg405484(PandP.40).aspx

Ho lavorato in alcuni progetti in cui non abbiamo implementato INotifyPropertyChanged nei nostri modelli e per questo abbiamo dovuto affrontare molti problemi; In VM era necessaria la duplicazione non necessaria delle proprietà e allo stesso tempo dovevamo aggiornare l’object sottostante (con valori aggiornati) prima di passarli a BL / DL.

Affronterai problemi specialmente se hai bisogno di lavorare con la raccolta dei tuoi oggetti modello (diciamo in una griglia o lista modificabile) o modelli complessi; gli oggetti del modello non verranno aggiornati automaticamente e dovrai gestire tutto ciò nella tua VM.


Originariamente risposto su un’altra domanda simile, aggiungendo qui in quanto contiene imp. dettagli mancanti da questo thread –

https://stackoverflow.com/a/6923833/45382

Supponiamo che il riferimento dell’object nella tua vista cambi. Come notificherete tutte le proprietà da aggiornare per mostrare i valori corretti? Chiamare OnPropertyChanged nella vista per tutte le proprietà dell’object è spazzatura dal mio punto di vista.

Quindi quello che faccio è lasciare che l’object stesso notifichi chiunque quando un valore in una proprietà cambia, e nella mia vista io uso i collegamenti come Object.Property1 , Object.Property2 e via. In questo modo se voglio solo cambiare l’object che è attualmente mantenuto nella mia vista, faccio semplicemente OnPropertyChanged("Object") .

Per evitare centinaia di notifiche durante il caricamento di oggetti, ho un indicatore booleano privato che l’ho impostato su true durante il caricamento che viene controllato dall’object OnPropertyChanged e non fa nulla.

Sto usando l’interfaccia INotifyPropertyChange in un modello. In realtà, una modifica della proprietà del modello dovrebbe essere triggersta solo dall’interfaccia utente o dal client esterno.

Ho notato diversi vantaggi e svantaggi:

vantaggi

Il notificatore è nel modello aziendale

  1. Come determinato dal dominio, è giusto. Dovrebbe decidere quando alzare e quando no.

svantaggi

Il modello ha proprietà (qty, rate, commission, totalfrieght). Totalfrieght è calcolato usando qty, rate, change di commissione.

  1. Al momento del caricamento dei valori da db, il calcolo totale di Frieght viene chiamato 3 volte (qty, rate, commissione). Dovrebbe essere una volta.

  2. Se la tariffa, qty è assegnata nel livello aziendale, viene chiamato di nuovo il notificatore.

  3. Ci dovrebbe essere un’opzione per disabilitare questo, possibilmente nella class base. Tuttavia, gli sviluppatori potrebbero aver dimenticato di farlo.

Normalmente ViewModel implementerà la proprietà INotifyPropertyChanged . Il modello può essere qualsiasi cosa (file xml, database o anche object). Il modello è usato per dare i dati al viewmodel, che si propaga alla vista.

Vedere qui

imho penso che viewmodel implementa INotifyPropertyChange e il modello potrebbe utilizzare la notifica su un “livello” diverso.

ad es. con alcuni servizi di documenti e un object di documento si ha un evento documentChanged che un viewmodel ascolta per cancellare e ribuild la vista. Nel modello di modifica di modifica si dispone di un propertychange per le proprietà del documento per supportare le viste. Se il servizio fa molto con il documento in fase di salvataggio (aggiornamento della data di modifica, ultimo utente e così via) è facile ottenere un sovraccarico di eventi Ipropertychanged e basta un documento modificato.

Ma se utilizzi INotifyPropertyChange nel tuo modello, penso che sia una buona pratica INotifyPropertyChange nel tuo viewmodel invece di iscriverti direttamente alla tua visualizzazione. In quel caso, quando gli eventi cambiano nel tuo modello, devi solo cambiare il modello di visuale e la vista rimane intatta.