2010-10-01 9 views
7

Prima di tutto non sono arrabbiato, perché uso MVVM in WinForms-) So del pattern MVP (Model View Presenter) e delle sue varianti. Ma quando ho iniziato questo progetto stavo per imparare WPF e usarlo, ma sono costretto ad affrettare lo sviluppo del programma, e non ho tempo per imparare WPF, quindi devo scriverlo in WinForms che conosco bene.Windows Forms (WinForms) Modello Visualizza ViewModel pattern (MVVM) a DataBind o no

Quindi, in breve, ho una grande applicazione client orientata ai dati, che è vicina alla fine, ho tutti i modelli e ViewModels fatto (infrastruttura, dominio, presentazione fatta) l'interfaccia utente è stata fatta, ora ho solo bisogno di collegare l'interfaccia utente a ViewModels. Per prima cosa ho iniziato a cablarlo utilizzando il metodo standard winforms (BindingSources e semplice associazione dati) ma quando ho eseguito il 30-50% del binding ho scoperto che il mio programma funziona molto lentamente, ho 100-150 proprietà associate totali finora, 30 di sono binding di entità di dominio (radice aggregata) al suo EditForm. Quindi il database non funziona bene in questa situazione, molti aggiornamenti non necessari, aggiornamenti a cascata dell'intera vista quando qualcosa di piccolo cambia, comportamento poco chiaro e altre cose brutte. Ha un odore di codice molto inaffidabile, sul quale ho poco controllo. Così ho iniziato a riscrivere il cablaggio come puro codice WinForms pulito (sottoscrivendo gli eventi PropertyChange e ListChanged e impostando la proprietà ViewModels da solo dall'interfaccia utente). Un sacco di codice da scrivere ma funziona molto più velocemente, ho il pieno controllo su questo e mi sento molto più affidabile. Allora, qual è il tuo pensiero su questo ragazzi? Qualcuno aveva una tale esperienza? Qual è il tuo verdetto su "To DataBind o Not"?

+1

vedi anche http://stackoverflow.com/questions/654722/implementing-mvc-with-windows-forms/682216#682216 –

risposta

1

L'utilizzo di associazione dati in WinForms è molto doloroso e la sottoscrizione agli eventi INotifyPropertyChanged e le operazioni manuali sono eccessive. Mi piace molto MVVM anche su WinForms per la sua grande testabilità e manutenibilità, ma non a un prezzo di 3 volte più codice da scrivere. Quindi per il nuovo codice che uso ora combinato View + ViewModel.

+0

Quando dici View + ViewModel combinato, intendi che inserisci le tue proprietà nel codice del modulo e poi lo usi come origine dati dell'oggetto? Stavo pensando di farlo. –

+0

Il tuo propgram è lento perché 'BndingSource' aggiorna tutte le proprietà di VIewModel se qualcuno è stato modificato nella vista per impostazione predefinita. Usa 'DataSourceUpdateMode.Never' su DataBinding nella VIew. E 'NotifyPropertyChanged' sulle proprietà ViewModel, quindi avere il controllo di Databinding – Fabio

6

Si potrebbe dare un'occhiata a Truss. Fornisce un gestore di binding in stile WPF che funziona su POCO. Rende molto più efficace l'utilizzo di MVVM con Windows Form.

+0

Molto interessante, è quasi la soluzione che ho fatto per me stesso, ho scritto io stesso con un po 'di riflessione ma agisce solo sugli oggetti INotifyPropertyChanged quindi ho dovuto sottoclasse i controlli di WinForms e sovrascrivo le proprietà di cui ho bisogno, stavo per fare qualche AOP Iniezione di codice di stile in setter di proprietà utilizzando Spring Framework, ma ho fallito in questo non abbastanza tempo, abilità. Usano qualche tipo di iniezione di codice in setter? –

+0

No: funzionano direttamente su POCO che implementano INPC. È piuttosto lucido. –

+0

Bello, ho visto il loro SRC, la stessa cosa che ho fatto, il mio e le loro fonti sono molto vicine, e l'utilizzo è lo stesso, immagino difficile da implementare in questo modo :-) Ma come nel mio caso questa associazione funziona solo sugli oggetti INPC , quindi per associarlo ad ad esempio ComboBox.SelectedItem Dovrò fare MyCombobox: INPC {object SelectedItem {set {base.SelectedItem = valore; OnpropertyChanged} e sfortunatamente anche in questo modo non funziona bene, un sacco di eventi fire propety bug nei controlli di WinForms, dovrò riscriverli (ho provato anche questo, molto lavoro, ne ho fatti). –

1

Un'altra possibilità è utilizzare un componente BindingSource ereditato per l'associazione dati in WinForms. Ad esempio: http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/. Funziona senza intoppi anche negli ambienti NET CF.

ho modificato l'attuazione di raggiungere due obiettivi:

  • un facile supporto di associazione dati per le mie ViewModels tramite WinForms progettista
  • supporto multithreading con Control.Invoke perché il default BindingSource non lo supporta. Ora reagisce agli eventi PropertyChanged da un thread in background.

Qui è la mia semplice classe ViewModelBindingSource:

public class ViewModelBindingSource : BindingSource 
{ 
    private readonly Control _control = new Control(); 
    private object _viewModel; 
    private Type _viewModelType; 

    public ViewModelBindingSource() 
    { 
    } 

    public ViewModelBindingSource(IContainer container) 
     : base(container) 
    { 
    } 

    public ViewModelBindingSource(object dataSource, string dataMember) 
     : base(dataSource, dataMember) 
    { 
    } 

    public object ViewModel 
    { 
     get { return _viewModel; } 
     set { _viewModel = value; } 
    } 

    public Type ViewModelType 
    { 
     get { return _viewModelType; } 
     set 
     { 
      if (value != null) 
      { 
       // save the type of our viewmodel 
       _viewModelType = value; 
       // create an instance of our viewmodel - so we don't need codebehind 
       _viewModel = Activator.CreateInstance(_viewModelType); 
       // add the viewmodel instance to the internal IList collection of the bindingsource 
       Add(_viewModel); 
       // move to the first element 
       MoveFirst(); 
       // set the datasource of the binding source to the first element 
       // this is necessary for data binding of all windows forms controls 
       DataSource = this[0]; 
      } 
     } 
    } 

    /// <summary> 
    /// Pass the call to the main thread for windows forms 
    /// This is needed for multithreading support. 
    /// </summary> 
    /// <param name="e"></param> 
    protected override void OnListChanged(ListChangedEventArgs e) 
    { 
     if (_control != null && _control.InvokeRequired) 
      _control.Invoke(new Action<ListChangedEventArgs>(OnListChanged), e); 
     else 
     { 
      base.OnListChanged(e); 
     } 
    } 
Problemi correlati