Изменение вида для ViewModel
Я пытаюсь реализовать проект MVVM для приложения mt WPF. Чтобы подключить представление к режимам просмотра, я использую ResourceDictionary
(используемый в Application.Resources
), который выглядит как
Модели представления затем просто помещаются в презентаторы содержимого для их отображения.
Теперь, когда пользователь нажимает кнопку, я хотел бы отобразить SampleViewModel
используя другое представление. Как изменить шаблон данных, используемый для SampleViewModel
?
- WPF TreeView: как стилизовать выбранные элементы с закругленными углами, как в Explorer
- Bind TextBox при нажатии клавиши Enter
- WPF WebBrowser Control - позиция: фиксированный Перемещение элемента при прокрутке (Windows 8)
- как программно перемещать мышь, щелкнуть, правым кликом и нажатием клавиши и т. д. в winform и wpf?
- WPF MVVM Зачем использовать ContentControl + DataTemplate Views, а не прямые XAML Window Views?
- Image UriSource и привязка данных
- Как связать несколько значений с одним текстовым блоком WPF?
- WPF. Как я могу сосредоточить все элементы в WrapPanel?
- Редактирование одного клика в WPF DataGrid
- В каких сценариях замораживание объектов WPF значительно повышает производительность?
- Передача параметров между режимами просмотра
- WPF: отобразить значение bool как «Да» / «Нет»
- Водяной знак / текст подсказки / заполнитель TextBox
Меньше слов больше кода. Насколько вы сказали, у вас есть class SampleViewModel
. Я добавил свойство Title
для демонстрации и ViewType
для определения правильного вида:
public enum ItemViewType { View1, View2 }; public class SampleViewModel { public string Title { get; set; } public ItemViewType ViewType { get; set; } }
DataTemplateSelector
для двух видов в зависимости от свойства 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; } }
Код Xaml:
Основная часть находится в classе MainViewModel
где я поставил логику переключения видов:
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"); } } }
SwitchViewCommand
может быть любой командой, я использую команду из библиотеки mvvmlight.
Внутри обработчика команды я изменяю тип viewmodel и изменяю свойство ItemViewModel
непростым способом, потому что ContentControl
обновляет представление только в том случае, если изменить свойство Content, и это свойство не будет изменено, если вы не установите ссылку на другой объект ,
Я имею в виду, даже код this.ItemViewModel = this.itemViewModel
не изменит представление. Это странно, но обходной путь не требует много работы.
Вы можете достичь этого по-разному, зависит от архитектуры, которую вы хотите.
- Вы можете написать собственный DataTemplateSelector и использовать его в ContentControl.ContentTemplateSelector и правильно выбрать эти два шаблона
- Если этот шаблон изменения представления происходит во многих разных местах и более частый UX, я бы также рекомендовал эти два представления переключиться с использованием DataTemplate.DataTrigger на основе свойства в SampleViewModel [я предполагаю, что у вас может быть отличительное свойство в ViewModel для знать это состояние]
Вы можете переопределить отображение, разместив в дереве аналогичный ресурс. Поскольку WPF разрешит ресурс путем поиска вверх, такое переопределение заменит существующее сопоставление.