2010-10-01 22 views
7

Primero no estoy enojado, porque uso MVVM en WinForms-) Conozco el patrón MVP (Model View Presenter) y sus variantes. Pero cuando comencé este proyecto iba a aprender WPF y usarlo, pero me veo obligado a acelerar el desarrollo del programa, y ​​no tengo tiempo para aprender WPF, así que tengo que escribirlo en WinForms, que sé muy bien.Windows Forms (WinForms) Modelo Ver modelo de modelo de vista (MVVM) a DataBind o no

En resumen, tengo una gran aplicación de cliente inteligente orientada a datos, que está a punto de terminar, tengo todos los Modelos y Modelos de Vista hechos (Infraestructura, Dominio, Presentación hecha) La IU también está hecha, ahora solo necesito cablear la IU a ViewModels. Primero comencé a cablearlo usando winforms estándar (BindingSources y databinding simple) pero cuando hice 30-50% de binding descubrí que mi programa funciona muy lento, tengo como 100-150 propiedades vinculadas total hasta el momento, 30 de son enlaces de entidad de raíz de dominio (raíz agregada) a su EditForm. Por lo tanto, el enlace de datos no funciona bien en esta situación, muchas actualizaciones innecesarias, actualizaciones en cascada de toda la vista cuando algo cambia pequeño, comportamiento poco claro y otras cosas feas. Huele a código muy poco confiable, sobre el cual tengo poco control. Así que empecé a reescribir el cableado como un código puro de WinForms (suscribiéndose a los eventos PropertyChange y ListChanged, y estableciendo la propiedad ViewModels por mi cuenta desde la interfaz de usuario). Gran cantidad de código para escribir, pero funciona mucho más rápido, tengo control total sobre esto, y se siente mucho más confiable. Entonces, ¿qué piensas de este tipo? ¿Alguien tuvo tal experiencia? ¿Cuál es su veredicto sobre "Para el enlace de datos o no"?

+1

ver también http://stackoverflow.com/questions/654722/implementing-mvc-with-windows-forms/682216#682216 –

Respuesta

1

Usar el enlace de datos en WinForms es realmente doloroso, y suscribirse a eventos INotifyPropertyChanged y hacer cosas manualmente es excesivo. Realmente me gusta MVVM incluso en WinForms por su gran capacidad de prueba y mantenimiento, pero no a un precio de 3X veces más código para escribir. Entonces, para el nuevo código, uso ahora View + ViewModel combinado.

+0

Cuando dice que View + ViewModel combinado ¿quiere decir que coloca sus propiedades en el código del formulario y luego lo utiliza como su fuente de datos objeto? Estaba pensando en hacer esto. –

+0

Su propgrama fue lento porque 'BndingSource' actualiza todas las propiedades de VIewModel si se cambió alguna en la vista de manera predeterminada. Use 'DataSourceUpdateMode.Never' en DataBinding in the VIew. Y 'NotifyPropertyChanged' en las propiedades de ViewModel, luego tiene el control de Databinding – Fabio

6

Es posible que desee echar un vistazo a Truss. Proporciona un administrador de enlace de estilo WPF que funciona en POCO. Hace que usar MVVM con Windows Forms sea mucho más efectivo.

+0

muy interesante, es casi la solución que hice para mí, escribí el gestor de databinder pequeño de UI agnóstico con algunas reflexiones pero funciona solo en objetos INotifyPropertyChanged así que tuve que subclasificar los controles de WinForms y anular las propiedades que necesitaba, iba a hacer algunos AOP Inyección de código de estilo en establecedores de propiedades utilizando Spring Framework, pero fallé en este tiempo no suficiente, habilidad. ¿Usan algún tipo de inyección de código en setters? –

+0

No, trabajan directamente en POCO que implementan INPC. Es bastante resbaladizo. –

+0

Bueno, miré su SRC, lo mismo que hice, mi y sus fuentes están muy cerca, y el uso es el mismo, supongo que es difícil implementarlo de otra manera :-) Pero como en mi caso, este enlace funciona solo en objetos INPC , para vincularlo, por ejemplo, a ComboBox.SelectedItem Tendré que hacer MyCombobox: INPC {object SelectedItem {set {base.SelectedItem = value; OnpropertyChanged} y desafortunadamente incluso así no funciona bien, montones de eventos de incendios \ propety establecieron errores en los controles de WinForms, tendré que volver a escribirlos (lo intenté también, montones de trabajo, hice algunos) –

1

Otra posibilidad es utilizar un componente BindingSource heredado para el enlace de datos en WinForms. Por ejemplo: http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/. Funciona sin problemas incluso en entornos NET CF.

He modificado la implementación para lograr dos objetivos:

  • un soporte de enlace de datos fácil para mis ViewModels través diseñador de Windows Forms
  • soporte multihilo con Control.Invoke porque el BindingSource por defecto no lo soporta. Ahora reacciona a eventos PropertyChanged de un hilo de fondo.

Aquí es mi clase simple 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); 
     } 
    } 
Cuestiones relacionadas