WPF MVVM просматривает просмотры
У меня есть приложение WPF с несколькими представлениями. Я хочу переключиться с вида 1 на вид 2, и оттуда я могу переключиться на несколько видов. Поэтому я хочу кнопку на представлении 1, которая загружает представление 2 в том же окне.
Я пробовал эти вещи, но не могу заставить его работать.
Из первой ссылки проблема в том, что я не понимаю код ViewModelLocator. Они вызывают CreateMain();
функция, но где это определено, и как я могу переключиться на другое представление изнутри представления.
Ответы
Ответ 1
Во-первых, вам не нужны какие-либо из этих наборов инструментов/фреймворков для реализации MVVM. Это может быть так просто, как это... допустим, что мы имеем MainViewModel
и PersonViewModel
и a CompanyViewModel
, каждый со своим родственным представлением и каждый из которых расширяет базовый класс abstract
BaseViewModel
.
В BaseViewModel
мы можем добавить общие свойства и/или ICommand
экземпляры и реализовать интерфейс INotifyPropertyChanged
. Поскольку все они расширяют класс BaseViewModel
, мы можем получить это свойство в классе MainViewModel
, которое может быть установлено для любой из наших моделей просмотров:
public BaseViewModel ViewModel { get; set; }
Конечно, вы бы правильно реализовали интерфейс INotifyPropertyChanged
на своих свойствах, в отличие от этого быстрого примера. Теперь в App.xaml
мы объявляем простой DataTemplate
для подключения представлений с моделями представлений:
<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
<Views:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:PersonViewModel}">
<Views:PersonView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:CompanyViewModel}">
<Views:CompanyView />
</DataTemplate>
Теперь, когда мы используем один из наших экземпляров BaseViewModel
в нашем приложении, эти DataTemplate
сообщают фреймворку отображать связанный вид. Мы можем отображать их следующим образом:
<ContentControl Content="{Binding ViewModel}" />
Итак, все, что нам нужно сделать сейчас, чтобы переключиться на новое представление, это установить свойство ViewModel
из класса MainViewModel
:
ViewModel = new PersonViewModel();
Наконец, как мы меняем представления из других представлений? Ну, есть несколько возможных способов сделать это, но самый простой способ - добавить Binding
из дочернего представления непосредственно в ICommand
в MainViewModel
. Я использую пользовательскую версию RelayComand
, но вы можете использовать любой тип, который вам нравится, и я предполагаю, что вы получите изображение:
public ICommand DisplayPersonView
{
get { return new ActionCommand(action => ViewModel = new PersonViewModel(),
canExecute => !IsViewModelOfType<Person>()); }
}
В дочернем представлении XAML:
<Button Command="{Binding DataContext.DisplayPersonView, RelativeSource=
{RelativeSource AncestorType={x:Type MainView}}, Mode=OneWay}" />
Что это! Наслаждайтесь.
Ответ 2
Когда я впервые начал с MVVM, я также боролся с различными MVVM-фреймами и особенно с навигационной частью. Поэтому я использую этот небольшой учебник, который я нашел, что создал Рейчел Лим. Это очень приятно и хорошо объяснено.
Посмотрите на него по следующей ссылке:
Надеюсь, это помогло вам:)
Ответ 3
Возможно эта ссылка поможет вам. Просто установите для свойства NavigateTo
представление, которое нужно отобразить в окне.
В качестве примера вы можете сделать что-то вроде
<Window x:Class="MainWindowView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:meffed="http:\\www.codeplex.com\MEFedMVVM"
meffed:ViewModelLocator.NonSharedViewModel="YourViewModel"
WindowStartupLocation="CenterScreen">
<Button meffed:NavigationExtensions.NavigateTo="firstview"
meffed:NavigationExtensions.NavigationHost="{Binding ElementName=_viewContainer}"
meffed:NavigationExtensions.NavigateOnceLoaded="False"
Visibility="Visible" />
<ContentControl x:Name="_viewContainer" Margin="0,0,0,10" />
<Window>
Тогда файл класса будет
public partial class MainWindowView : Window
{
public MainWindowView()
{
InitializeComponent();
}
public ContentControl ViewContainer { get { return _viewContainer; } }
}
Затем вы можете определить каждый вид как UserControl
, а затем используя ссылку, которую я дал выше, привяжите кнопку meffed:NavigationExtensions.NavigateTo="secondView"
. Чтобы настроить таргетинг на ContentControl
Window
, просто используйте привязку RelativeSource
. Например,
meffed:NavigationExtensions.NavigationHost="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}},Path=ViewContainer}"
В каждом представлении просто посмотрите, что вы комментируете код, лежащий в основе определения класса, с помощью [NavigationView("firstview")]
и т.д.
Сложно в первый раз, но это будет очень легко, как только вы поймете идею.
Ответ 4
<ContentControl x:Name="K.I.S.S" Content="{Binding ViewModel, Converter={StaticResource ViewLocator}}"/>