2013-05-02 9 views
10

Questa è più una questione di architettura/design.Come evitare un inferno di dati/eventi su uno schermo complesso?

Ho eseguito alcuni progetti in passato scritti in WPF/Windows Forms, ecc. Che hanno schermi complessi con molti campi e questi campi sono collegati tra loro (i loro valori dipendono l'uno dall'altro con qualche logica coinvolti).

Questi progetti che ho assunto dopo che sono stati implementati, e ho trovato molti eventi/dati si sono bloccati all'inferno. Ciò che intendo è che, poiché tutti questi campi dipendono da altri, hanno implementato INotifyPropertyChanged e altri campi sono essere modificato di conseguenza. Ciò fa sì che gli stessi campi vengano aggiornati 5-6 volte quando lo schermo viene caricato e l'ordine in cui vengono popolati i campi causa errori orribili. (Per esempio, Data è stato impostato prima Tipo di lavoro, anziché dopo Tipo di lavoro, così ho finire con un diverso Fee lavoro.)

A peggiorare le cose, alcuni hack sono implementati su Eventi di interfaccia utente (ad esempio, DropDown modificato per aggiornare il campo X) mentre altri sono nel modello di dominio a cui l'interfaccia utente si lega.

Fondamentalmente, è un gran casino, e voglio solo sapere qual è il modo migliore per implementare qualcosa del genere è se dovessi iniziare da zero. O è una buona idea evitare uno schermo così complesso in primo luogo?

risposta

0

Abbiamo interfacce utente abbastanza complesse (compresi diversi campi correlati di tipi diversi, ad esempio una riga in un DataGrid) e il modello MVVM ha funzionato abbastanza bene per noi. Tutti i beni provenienti dal modello e esposti alla vista che hanno logiche complesse correlate sono "avvolti" da una proprietà equivalente nella ViewModel, che non ha Backup campo, ma punta direttamente al Modello:

public class SomeComplexViewModel 
{ 

    public SomeModel Model {get;set;} 

    public string SomeCrazyProperty 
    { 
     get 
     { 
      return Model.SomeCrazyProperty; 
     } 
     { 
      Model.SomeCrazyProperty = value; 
      //... Some crazy logic here, potentially modifying some other properties as well. 
     } 
    } 
} 

<TextBox Text="{Binding SomeCrazyProperty}"/> 

Questo rimuove il problema del "valore iniziale", poiché il valore iniziale letto dal Binding è in realtà il valore reale proveniente dal modello, e quindi la logica inserita nello Setter viene eseguita solo quando necessario.

Poi, per le proprietà fittizi (che non hanno alcuna logica dietro), che si legano direttamente dalla vista al Modello:

<TextBox Text="{Binding Model.SomeRegularProperty}"/> 

Questo riduce la pesantezza nel ViewModel.

Per quanto riguarda gli eventi nel codice, evito completamente. Il mio codice dietro i file è quasi sempre uno InitializeComponent() e nient'altro.

Solo la logica specifica per la vista è inserita nel codice sottostante (come le animazioni ecc.).

Edit:

E 'importante ricordare che le WinForms funzionalità di associazione sono uno scherzo rispetto a quelli XAML-based. potrebbe essere la causa che stai vedendo quegli orribili pasticci in quei progetti?

2

Cercherei di mantenere il più possibile la logica di business degli impostori della proprietà.

Prima di tutto, se sono necessarie diverse proprietà per un calcolo, mi piacerebbe scrivere un metodo che fa il calcolo, e chiamare questo metodo quando appropriato. Per esempio. se tutte le diverse combinazioni di valori di proprietà hanno senso, si può semplicemente chiamare il metodo nei setter di ciascuna proprietà, assicurandosi che lo stesso codice venga eseguito ogni volta che viene modificata una delle proprietà. Se solo è possibile valutare combinazioni speciali di valori di proprietà, è possibile implementare un comando e consentire all'utente di decidere quando calcolare le modifiche risultanti, oppure è possibile fornire feedback tramite la convalida e valutare solo le modifiche alle proprietà se la combinazione è valida. Se ci sono diverse proprietà interdipendenti, io uso spesso una variabile "ChangeInitiator" per indicare quale proprietà è cambiato, in modo che sia chiaro nel metodo di calcolo, che proprietà è responsabile per il cambiamento e che gli altri devono cambiare di conseguenza. Fondamentalmente, questo è lo stesso di fare una parte del calcolo in ogni setter di proprietà, ma trovo che mi aiuta a mantenere una visione d'insieme delle cose se le diverse parti della relazione sono tutte in un unico metodo.

In un programma che ho scritto una volta, ho eseguito alcuni calcoli in esecuzione su un thread in background periodicamente, quindi dovrei semplicemente impostare un flag ogni volta che un pezzo di dati cambiava che richiedeva un nuovo calcolo e fare tutti gli aggiornamenti basati su un timer ogni secondo o così ... che potrebbe anche aiutarti a ottenere la logica più dritta, ed evita di far eseguire il calcolo più volte per un insieme di modifiche correlate.

Per quanto riguarda la notifica di modifica, mi piacerebbe molto provare a utilizzare solo per i dati di interfaccia utente vincolanti.

Problemi correlati