2010-10-01 5 views
7

Zuerst bin ich nicht wütend, weil ich MVVM in WinForms- verwenden- Ich weiß über MVP (Model View Presenter) -Muster und seine Varianten. Aber als ich mit diesem Projekt anfing, wollte ich WPF lernen und es benutzen, aber ich bin gezwungen, die Programmentwicklung zu beschleunigen, und habe keine Zeit, WPF zu lernen, also muss ich es in WinForms schreiben, die ich gut kenne.Windows Forms (WinForms) Modell Ansicht ViewModel Muster (MVVM) zu DataBind oder nicht

Kurz gesagt, ich habe eine große Daten orientierte Smart-Client-Anwendung, die kurz vor dem Abschluss ist, habe ich alle Modelle und ViewModels getan (Infrastruktur, Domain, Präsentation getan) UI ist auch getan, jetzt muss ich nur UI zu verbinden zu ViewModels. Zuerst fing ich an, es unter Verwendung der Standard winforms Weise (BindingSources und einfache Datenbindung) zu verdrahten, aber als ich 30-50% der Bindung fand, fand ich heraus, dass mein Programm sehr langsam arbeitet, ich habe 100-150 gebundene Eigenschaften so weit, 30 von Sie sind Domain-Root-Entity (Aggregat-Root) -Bindungen an ihre EditForm. In dieser Situation funktioniert Datenbindung also nicht gut, viele unnötige Updates, Kaskaden-Updates der gesamten Ansicht, wenn sich etwas Kleines ändert, unklares Verhalten und andere hässliche Dinge. Es riecht nach sehr unzuverlässigem Code, auf den ich wenig Kontrolle habe. Also fing ich an, die Verkabelung als reinen WinForms-Code neu zu schreiben (ich abonniere PropertyChange- und ListChanged-Ereignisse und setze die ViewModels-Eigenschaft selbst von der Benutzeroberfläche aus). Viel Code zum Schreiben, aber es funktioniert viel schneller, ich habe die volle Kontrolle darüber, und es fühlt sich viel zuverlässiger an. Also, was denkst du über diese Jungs? Jeder hatte solche Erfahrung? Was ist dein Urteil über "To DataBind or Not"?

+1

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

Antwort

1

Die Verwendung von Datenbindung in WinForms ist wirklich schmerzhaft, und das Abonnieren von INotifyPropertyChanged-Ereignissen und das manuelle Ausführen von Aufgaben ist übertrieben. Ich mag MVVM sogar auf WinForms, weil es sehr gut zu testen und zu warten ist, aber nicht zu einem Preis, der dreimal so hoch ist wie beim Schreiben. Also für neuen Code benutze ich jetzt View + ViewModel.

+0

Wenn Sie kombinierte View + ViewModel sagen, meinen Sie, dass Sie Ihre Eigenschaften in den Formularcode hinter setzen und dann als Ihre Objektdatenquelle verwenden? Ich habe darüber nachgedacht. –

+0

Ihr Projekt war langsam, da 'BendingSource' alle Eigenschaften von View.Model aktualisiert, wenn in der Ansicht standardmäßig eine davon geändert wurde. Verwenden Sie 'DataSourceUpdateMode.Never' auf der DataBinding in der Ansicht. Und 'NotifyPropertyChanged' in den Eigenschaften des ViewModels, dann Kontrolle der Datenbindung – Fabio

6

Vielleicht möchten Sie einen Blick auf Truss werfen. Es bietet einen Bindungsmanager im WPF-Stil, der auf POCOs funktioniert. Es macht MVVM mit Windows Forms viel effektiver.

+0

Sehr interessant, Es ist fast die Lösung, die ich für mich selbst gemacht habe, ich habe UI agnostic kleinen Databinder-Manager selbst mit etwas Reflexion Zeug geschrieben, aber es funktioniert nur auf INotifyPropertyChanged Objekte, so musste ich WinForms-Steuerelemente Unterklasse und überschreiben die Eigenschaften, die ich brauche, ich würde einige AOP machen Stil-Code-Injektion in Property-Setter mit Spring Framework, aber ich scheiterte in dieser nicht genug Zeit, Fähigkeit. Verwenden sie eine Art Code-Injektion in Setter? –

+0

Nein - sie arbeiten direkt auf POCOs, die INPC implementieren. Es ist ziemlich glatt. –

+0

Schöne, schaute auf ihre SRC, das gleiche, was ich tat, meine und ihre Quellen sind ziemlich nah, und die Verwendung ist gleich, ich denke, schwer zu implementieren, anders :-) Aber wie in meinem Fall funktioniert diese Bindung nur auf INPC-Objekte , um es zum Beispiel an ComboBox zu binden.SelectedItem muss ich MyCombobox tun: INPC {object SelectedItem {set {base.SelectedItem = Wert; OnpropertyChanged} und leider auch so funktioniert es nicht gut, viele Event Fire Stuff \ Property setzen Bugs in WinForms Controls, ich werde sie neu schreiben müssen (ich habe es auch versucht, viel Arbeit, habe einiges getan.) –

1

Eine andere Möglichkeit ist die Verwendung einer geerbten BindingSource-Komponente für die Datenbindung in WinForms. Zum Beispiel: http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/. Es funktioniert reibungslos auch in NET CF-Umgebungen.

Ich habe die Umsetzung modifizierte zwei Ziele zu erreichen:

  • eine einfache Datenbindung Unterstützung für meine Viewmodel durch WinForms Designer
  • Multithreading-Unterstützung mit Control.Invoke, da der Standardbinding nicht unterstützt. Jetzt reagiert es auf PropertyChanged-Ereignisse von einem Hintergrund-Thread.

Hier ist meine einfache ViewModelBindingSource Klasse:

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); 
     } 
    } 
Verwandte Themen