2010-01-15 29 views
5

? He encontrado dos maneras de inicializar vistas y modelos de vista en WPF CAL MVVM.¿Cuál es la forma correcta de inicializar un modelo y ver en WPF CAL MVVM

1 - Parece ser más popular. Requiere que resuelva el ViewModel para resolver automáticamente la Vista. ViewModel contiene información sobre la Vista.

public interface IView 
    { 
     void SetModel(IViewModel model); 
    } 

    public interface IViewModel 
    { 
     IView View { get; } 
    } 

    public class View 
    { 
     public void SetModel(IViewModel model) 
     { 
      this.DataContext = model; 
     } 
    } 

    public class ViewModel 
    { 
     private IView view; 

     public ViewModel(IView view) 
     { 
      this.view = view; 
     } 

     public IView View { return this.view; } 
    } 

2 - Parece mucho más limpio y elimina la Vista del ViewModel. Requiere que resuelva la Vista para resolver automáticamente ViewModel. Inyecta objetos en la vista (No estoy seguro si esto es bueno o no).

public interface IView 
    { 
    } 

    public interface IViewModel 
    { 
    } 

    public class View 
    { 
     private IViewModel model; 

     public View(IUnityContainer unityContainer) 
     { 
      this.model = unityContainer.Resolve<IViewModel>(); 
      this.DataContext = this.model; 
     } 
    } 

    public class ViewModel 
    { 
    } 

¿Cuál es el método aceptado para inicializar las vistas y modelos y cuáles son las ventajas y desventajas de cada método. ¿Debería inyectar objetos en su vista?

Respuesta

3

Ambos son válidos, pero # 1 tiende a ser más comprobable (por lo menos hace que su pruebas más concisas). La ventaja del n. ° 2 es que tiende a ser más explícito y hace que el mantenimiento sea un poco más claro, especialmente cuando se tiene mucha rotación, ese tipo de cosas. Requiere menos explicaciones (aunque esta no es una razón para adoptarlo, es solo una perogrullada).

La diferencia es que # 1 se llama la inyección de dependencias y # 2 se llama Servicio de Localización. A menudo se confunden porque ambos generalmente utilizan algún tipo de contenedor IoC (aunque esto no tiene que ser el caso).

Al final es una cuestión de preferencias, pero como dije, creo que encontrará que el # 1 es mucho más fácil de probar ... no tendrá que involucrar a la interfaz IUnityContainer en sus pruebas/burlas.

1

La opción 1 se ve a la derecha, da a la vista una referencia al modelo de vista.

Tener viewmodels con una referencia de regreso a la vista me parece un poco sospechoso. Eso se parece más a una arquitectura de tipo modelo-vista-presentador. Si tiene viewmodels que interactúan con la vista y necesitan una referencia a la vista, sería mejor que dividiera el modelo de vista en un modelo de vista utilizado únicamente para el enlace de datos y un presentador que realiza una interacción más compleja.

La opción 2 no se ve nada bien. Pasar una referencia al contenedor ioc en clases es un gran olor a código en mi libro. Las llamadas a un contenedor de IoC deben minimizarse. En la mayoría de mis aplicaciones solo llamo al contenedor al inicio del programa para conectarlo. La creación más dinámica de objetos generalmente se hace con clases de fábrica.

+0

la ventana de propiedades en la opción 1 se ha encontrado por mí en varios ejemplos, pero estoy de acuerdo en que no debería estar allí. – anon

2

prefiero definir el modelo de vista en XAML y proporcionar una propiedad de sólo lectura para el acceso proporcionado:

<UserControl ...> 
    <UserControl.DataContext> 
     <local:MyViewModel/> 
    </UserControl.DataContext> 

    ... 

</UserControl> 

public partial class MyView : UserControl, IMyView 
{ 
    public MyViewModel ViewModel 
    { 
     get { return this.DataContext as MyViewModel; } 
    } 

    ... 
} 
+0

+1 para la propiedad de solo lectura –

1

El problema con este código es que la opción 2 está horneando más de lo necesario. Realmente no necesita ni debe tener una referencia al contenedor.

Una alternativa permite que la opción 2 sea tan comprobable como la opción 1, pero conceptualmente más clara en cuanto a que ViewModel nunca sabe acerca de la Vista.

Esto es particularmente útil si desea especificar su diseño con un archivo xml en lugar de utilizar las regiones de prisma, lo que le permite hacer el diseño fácilmente configurable.

Alternativa:

public interface IView 
{ 
} 

public interface IViewModel 
{ 
} 

public class View : IView 
{ 
    private IViewModel model; 

    public View(IViewModel m) 
    { 
     this.model = m; 
     this.DataContext = this.model; 
    } 
} 

public class ViewModel : IViewModel 
{ 
} 

y en otro lugar que tenga:

Container.RegisterType<IViewModel, ViewModel>(/* appropriate container config */); 
Container.RegisterType<IView, View>(/* appropriate container config */); 

y se puede crear una vista en cualquier lugar con:

Container.Resolve<IViewModel>(); 
+0

+1 para observar la resolución del tipo no es el trabajo de la vista. Yo uso este enfoque también y me encanta. – RMart

Cuestiones relacionadas