Cambiar la vista de un ViewModel

Estoy tratando de implementar el patrón de diseño de MVVM para la aplicación mt WPF. Para conectar la vista a viewmodels, uso ResourceDictionary (usado en Application.Resources ), que se parece a

    

Los modelos de vista se ponen simplemente en presentadores de contenido para mostrarlos.

Ahora, cuando el usuario presiona un botón, me gustaría mostrar SampleViewModel con una vista diferente. ¿Cómo cambio la plantilla de datos utilizada para SampleViewModel ?

Menos palabras más código. Por lo que dices, tienes la clase SampleViewModel . ViewType el Title propiedad para demostración y ViewType para identificar la vista correcta:

 public enum ItemViewType { View1, View2 }; public class SampleViewModel { public string Title { get; set; } public ItemViewType ViewType { get; set; } } 

DataTemplateSelector para dos vistas según la propiedad ViewType :

 class ItemViewTemplateSelector : DataTemplateSelector { public DataTemplate View1Template { get; set; } public DataTemplate View2Template { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { var vm = item as SampleViewModel; if (vm == null) return null; switch (vm.ViewType) { case ItemViewType.View1: return View1Template; case ItemViewType.View2: return View2Template; } return null; } } 

Código Xaml:

                 

La parte principal está en la clase MainViewModel donde puse la lógica para cambiar de vista:

 public class MainViewModel : ViewModelBase { public MainViewModel() { this.ItemViewModel = new SampleViewModel { Title = "Some title", ViewType = ItemViewType.View1 }; this.SwitchViewCommand = new RelayCommand(() => { this.ItemViewModel.ViewType = this.ItemViewModel.ViewType == ItemViewType.View1 ? ItemViewType.View2 : ItemViewType.View1; //The magic senquence of actions which forces a contentcontrol to change the content template var copy = this.ItemViewModel; this.ItemViewModel = null; this.ItemViewModel = copy; }); } public RelayCommand SwitchViewCommand { get; set; } private SampleViewModel itemViewModel; public SampleViewModel ItemViewModel { get { return itemViewModel; } set { itemViewModel = value; RaisePropertyChanged("ItemViewModel"); } } } 

El SwitchViewCommand puede ser cualquier tipo de comando, yo uso el comando de la biblioteca mvvmlight.

Dentro del manejador del comando cambio el tipo de viewmodel y actualizo la propiedad ItemViewModel de una manera complicada porque ContentControl actualiza una vista solo si se cambia la propiedad Content, y esta propiedad no se cambiará a menos que establezca una referencia a un objeto diferente .

Quiero decir, incluso el código this.ItemViewModel = this.itemViewModel no cambiará la vista. Es extraño, pero la solución no requiere mucho trabajo.

Puede lograr esto de muchas maneras diferentes depende de la architecture que desee.

  • Puede escribir un DataTemplateSelector personalizado y usarlo en ContentControl.ContentTemplateSelector y elegir esas dos plantillas de manera apropiada
  • Si este patrón de cambio de la vista se produce en muchos lugares diferentes y en UX más frecuentes, también recomendaría esas dos vistas alternadas usando un DataTemplate.DataTrigger basado en una propiedad en SampleViewModel [Supongo que podría tener una propiedad distintiva en ViewModel para saber ese estado]

Puede anular la asignación colocando un recurso similar más abajo en el árbol. Dado que WPF resolverá el recurso buscando hacia arriba, dicha anulación reemplazará su asignación existente.