2010-12-08 12 views
5

Digamos que tengo dos vistas en mi aplicación, MemberListView y MemberEditView. Están asociados con su perspectiva viewModels, MemberListViewModel y MemberEditViewModel. Los modelos hablan sobre una clase de repositorio, MemberRepository, que tiene los métodos CRUD para la clase miembro.Pregunta de MVVM y repositorio

En el formulario MemberEditView, tengo varias listas desplegables que muestran mensajes como Estado (Activo/Inactivo/Pendiente), los miembros comercian código, etc. Son objetos ObservableCollection en mi viewModel y están vinculados a ComboBoxes en la vista. ¿Debería el MemberRepository manejar los get para recuperar las listas de cada uno que se mostrarán?

¿Qué pasa si en el MemberEditView tengo una cuadrícula que muestra todos los trabajos que el miembro ha tenido en los últimos años. Si el usuario hace doble clic en uno de los trabajos, llama a JobHistoryEditView para mostrar la información del trabajo y tiene un JobHistoryViewModel. ¿Debería el MemberRepository hacerse cargo de los métodos CRH de JobHistory o debería tener un repositorio de JobHistory por separado?

aplicaciones

Respuesta

2

más MVVM tendrían esta arquitectura:

View -> ViewModel -> Model -> Repository 

Recientemente he sido abrazar una variante:

View -> ViewModel <- Presenter -> Model -> Repository 

(Donde A -> B significa "A sabe sobre B", pero B no sabe acerca de A.)

Observe que en ambos casos, lo único que conoce sobre el repositorio es el modelo, no el modelo de vista. Su modelo no es solo las entidades de dominio, sino que también debe albergar la lógica comercial. Obviamente uno de los casos de uso de su lógica de negocio tiene que soportar es algo que llamaré una MemberEditTask:

public class MemberEditTask 
{ 
    private readonly Member _member; 

    public MemberEditTask(Member member, IRepository repository) 
    { 
     this._member = member; 
     this.StatusChoices = repository.GetPossibleMemberStatuses(member); 
    } 

    public ReadOnlyCollection<MemberStatus> StatusChoices { get; private set; } 

    public MemberStatus Status 
    { 
     get { return this._member.Status; } 
     set 
     { 
      if(!this.StatusChoices.Contains(value)) 
      { 
       throw new ArgumentOutOfRangeException(); 
      } 
      this._member.Status = value; 
     } 
    } 
} 

Todo esto pertenece lógica en su modelo debido a que la lista de posibles opciones (y validar que una de ellas era realmente elegido) se define por lógica de negocios. También podría imaginarse algo más que consuma el MemberEditTask, como un proceso automatizado que se ejecuta en el servidor que edita un miembro en respuesta a un archivo cargado en un servidor FTP o un proceso en segundo plano (estableciendo el estado en Inactivo después de una cierta cantidad de tiempo) Todas estas cosas necesitan ejecutar las mismas reglas de negocio, por lo que todo tiene que ser común (no en ViewModel).

Por lo tanto, dado que la clase, la clase ViewModel es así:

public class MemberEditViewModel : ViewModelBase 
{ 
    private readonly MemberEditTask _task; 

    public MemberEditViewModel(MemberEditTask task) 
    { 
     this._task = task; 
    } 

    public IEnumerable<MemberStatus> StatusChoices 
     { get { return this._task.StatusChoices; } 

    public MemberStatus Status 
    { 
     get { return this._task.Status; } 
     set 
     { 
      this._task.Status = value; 
      NotifyAllPropertiesChanged(); 
     } 
    } 
} 

En este caso, como muy simple conveniencia, simplemente creen que NotifyAllPropertiesChanged es un método protegido de ViewModelBase que utiliza la reflexión para criar a un PropertyChanged evento en todos propiedades públicas de ViewModel. :) Eso es exagerado, por supuesto, pero conduce en un punto más importante ...

Esto es casi un ejemplo tonto porque en este caso, MemberEditViewModel es innecesario. Si la Vista es la única configuración Status, ¡entonces realmente no es necesario elevar el evento de cambio de propiedad! Por supuesto, en el mundo real, tendrá más propiedades y habrá interacciones. La razón por la que ViewModel existe es notificar a los consumidores cuando cambian sus propiedades relacionadas con la vista, que es algo que el Modelo no hace (y no debería, en mi opinión). (El ViewModel también tiene una lógica específica de Vista adicional para admitir animaciones, etc.)

Volviendo a su pregunta ...si el MemberRepository es responsable de ejecutar los get de los estados es irrelevante desde el punto de vista de ViewModel porque el repositorio es un servicio utilizado por el Modelo. El modelo es un servicio utilizado por ViewModel. Haga que su Modelo de la tarea/flujo de trabajo/proceso/lo que sea exponga la lista de opciones de estado.

Lo siento si fue largo aliento.