2012-12-12 11 views
7

Esempi di app WVF MVVM che ho visto su Internet considerano VM un livello che interagisce con un livello di servizio che utilizza "vecchi" eventi da una libreria esterna o interagisce con web usando HTTP o qualsiasi altra cosa. Ma cosa succede se costruisco personalmente M, V, VM, assistenza e altre parti? Come costruire correttamente l'interazione tra il livello di servizio e il livello viewmodel? Posso semplicemente inserire ObservableCollection<OrderModel> nel servizio e restituirlo come è da viewmodel per la visualizzazione, oppure è considerato un approccio errato e ci sono alternative migliori?ObservableCollection nel livello di servizio dell'applicazione MVVM WPF

risposta

6

È possibile farlo, ovviamente è possibile. La ragione principale per fare una cosa del genere sarebbe ridurre la duplicazione tra più applicazioni WPF.

Tuttavia, una sfida che si potrebbe avere in alcuni scenari, a seconda dell'implementazione del livello di servizio/livello dati, è costituita da servizi a esecuzione prolungata che utilizzano a loro volta connessioni al database. ObservableCollections sono allettanti dal punto di vista del fatto che il livello di servizio sincronizzi automaticamente le modifiche apportate da un'applicazione a un archivio dati; tuttavia diventa complicato quando si desidera comunicare le modifiche che hanno origine dai dati stessi (ad esempio in risposta ad un altro processo che crea/modifica dati).

Il livello di servizio non può realmente sostituire l'istanza (cioè nel caso di modifiche su larga scala), poiché non è più l'unico proprietario del riferimento - ma anche se fosse possibile, sostituire l'istanza sarebbe praticamente interrompere qualsiasi legame che l'interfaccia utente ha alla raccolta.

Quindi ti limiti a cercare di mantenere aggiornata l'istanza. Se i tuoi servizi sono collegati a un database, a meno che tu non codifichi qualche forma di processo di monitoraggio a lungo termine all'interno del tuo servizio, l'unico modo semplice per tenere aggiornato un ObservableCollection dopo che è stato distribuito sarebbe quello di mantenere le connessioni al database/contesti (nel caso di Linq to Sql o EF) aperti - perché altrimenti oggetti correlati ecc. non saranno in grado di essere recuperabili (a meno che non si impongano tutti gli oggetti da leggere in una volta sola - che non è scalabile).

Ok, quindi è possibile scrivere qualche forma di livello di gestione che può gestire le connessioni per te - ma oltre all'inevitabile polling, o forse alle notifiche di SQL Server che potresti usare, credo che il codice potrebbe diventare piuttosto complicato .

Detto questo, dipende davvero - quel particolare problema è uno da tenere a bada, ma potrebbe essere che tu abbia un'architettura e un ambiente in cui queste cose semplicemente non contano.

Il mio consiglio, se volete provarlo, andare avanti. Per me? Ci ho pensato - e oltre ad aggiungere INotifyPropertyChanged ad alcuni modelli di dominio, mi associo all'idea che un'applicazione abbia la sua VM. Più applicazioni potrebbero condividere la stessa VM, ma questa non sarà interna al livello di servizio stesso.

Un livello di servizio fornisce accesso ai dati e alla logica di business in un modo tipicamente one-shot. Le classi nel pattern VM hanno una durata di vita molto più lunga, e il tentativo di codificare un layer di servizio di lunga durata è notoriamente molto difficile da fare, specialmente se si desidera provare a risolvere tutti i problemi che potrebbero presentarsi in tutte le applicazioni future. Inevitabilmente finirai per codificare servizi o tipi di VM all'interno del livello di servizio solo per una singola applicazione - nel qual caso potrebbe anche essere entrato nella base di codici dell'app.

0

Non lo farei per una serie di motivi. Sono documentati qui: Common mistakes with an observable collection

L'autore passa attraverso diversi errori che le persone fanno con loro, compreso il loro utilizzo nel livello di servizio.

+0

L'articolo dice nella sezione "Usarlo nel modello" che l'utilizzo di OC nei modelli è negativo, ma ho visto molti esempi quando i modelli vengono forniti come sono nella vista, senza alcuna conversione. Uno dei consigli era: "Se un modello implementa INotifyPropertyChanged, usalo, altrimenti convertilo". Quindi usare le collezioni osservabili nei modelli non è considerato una cattiva pratica da parte di tutti ... Comunque, la domanda è: qual è il modo alternativo, giusto? – Athari

+0

Credo che il modo alternativo (il modo giusto) sia usare IEnumerable. Come suggerito da @PeteH, prova ad utilizzare solo OC il più lontano possibile, ovvero nel tuo ViewModel. E scrivi una classe CollectionViewModel che espone ObservableCollection di ViewModels come una proprietà, con iscrizioni a OnCollectionChanged, ecc. – Heliac

2

Sarei tentato di utilizzare una ObservableCollection solo dal punto in cui è pertinente l'aspetto "osservabile", che è in genere la VM che espone qualcosa al V. Più in basso nello stack (cioè la M) I'd essere tentati di attenersi a cose più generiche come elenchi e raccolte (a meno che non sia specificamente necessario che le cose siano diversamente). È abbastanza facile per la VM creare in ogni caso una ObservableCollection basata su qualsiasi vecchio IEnumerable.

Una domanda ragionevole, però, soprattutto come il posizionamento di ObservableCollection nel namespace System.Collections sembrerebbe suggerire che Microsoft non particolarmente pensare a questo come un classe specializzata (e certamente non-WPF specifico).

+0

Il problema con l'attaccamento alle liste "tradizionali" ed enumerabili, è che ho ancora bisogno di aggiornare la vista tramite viewmodel quando qualcosa è aggiunto alla lista; pertanto viewmodel deve essere avvisato di un nuovo elemento dal servizio. Se aggiungo eventi, sembrerà un'implementazione errata (e probabilmente buggy) della collezione osservabile ... – Athari

+0

@Athari Posso vedere da dove vieni - non ha certamente senso implementare la tua ObservableCollection. Guardando più in basso, come farà il servizio a sapere che le cose sono cambiate? – PeteH

+0

@Athari - Questo è esattamente quello che faccio. Quando aggiungo un nuovo elemento a livello di codice (ovvero non utilizzo la nuova riga DataGrid, ma aggiungo un'entità), ho un evento OnEntityAdded che aggiungo al metodo Create nel mio repository: ** OnEntityAdded (new ModelEntityAddedEventArgs (entity)) ** . Come puoi vedere, l'entità viene passata negli argomenti dell'evento. Il mio livello di servizio si iscrive a questo evento. – Heliac