WPF MVVM Зачем использовать ContentControl + DataTemplate Views, а не прямые XAML Window Views?
У меня вопрос о MVVM в WPF, который меня заводит.
Зачем делать следующее:?
MainWindow.xaml:
<Window x:Class="MVVMProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ContentControl Content="{Binding}"/>
</Grid>
</Window>
Создайте ли ваш ExampleView.xaml как:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
<DataTemplate DataType="{x:Type vms:ExampleVM}" >
<Grid>
<ActualContent/>
</Grid>
</DataTemplate>
</ResourceDictionary>
И создайте окно следующим образом:
public partial class App : Application {
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
MainWindow app = new MainWindow();
ExampleVM context = new ExampleVM();
app.DataContext = context;
app.Show();
}
}
Когда вы можете сделать это следующим образом:?
App.xaml: (Установить начальное окно /View )
<Application x:Class="MVVMProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="ExampleView.xaml">
</Application>
ExampleView.xaml: (a Window not a ResourceDictionary)
<Window x:Class="MVVMProject.ExampleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
>
<Window.DataContext>
<vms:ExampleVM />
</Window.DataContext>
<Grid>
<ActualContent/>
</Grid>
</Window>
По существу это "Просмотр как DataTemplate" (VaD) и "Просмотр как окно" (VaW)
Вот мое понимание сравнения: (Примечание: я использую VS 2008, поэтому мне не хватает Blendability &/или другого материала)
- VaD: позволяет переключать виды, не закрывая окно. (Это нежелательно для моего проекта)
- VaD: VM ничего не знает о представлении, тогда как в VaW он (только) должен иметь возможность создавать экземпляр при открытии другого окна
- VaW: Я действительно вижу, что мой xaml отображается в Дизайнере (я не могу
с VaD, по крайней мере, в моей текущей настройке)
- VaW: работает интуитивно с
открытие и закрытие окон; каждое окно имеет (есть) соответствующий вид
(и ViewModel)
- VaD: ViewModel может передавать начальную ширину окна, высоту, изменяемость и т.д. через свойства (тогда как в VaW они непосредственно устанавливаются в окне)
- VaW: Можно установить FocusManager.FocusedElement(не уверен, как в VaD)
- VaW: Меньше файлов, так как мои типы окон (например, Ribbon, Dialog) включены в их представления
Итак, что здесь происходит? Не могу ли я просто создать свои окна в XAML, получить доступ к их данным по свойствам виртуальной машины и сделать с ними? Кодировка - то же самое (фактически ноль). Я пытаюсь понять, почему я должен перетасовать все материалы View в ResourceDictionary.
(Но я не хочу делать это неправильно;-))
Это даже имеет значение? Есть что-то, что я пропустил?
Большое спасибо за чтение.: О
Спасибо Рейчел Лим и Ник Поляк за мое расцветное понимание MVVM
Изменить: незначительное изменение потока
Ответы
Ответ 1
Люди используют DataTemplates
таким образом, когда они хотят динамически переключать Views в зависимости от ViewModel:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:VM1}">
<!-- View 1 Here -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:VM2}">
<!-- View 2 here -->
</DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding}"/>
</Window>
Итак,
если Window.DataContext
является экземпляром VM1
, тогда будет отображаться View1
,
и если
Window.DataContext
- это экземпляр VM2
, тогда будет отображаться View2
.
Конечно, это не имеет никакого смысла, если ожидается только 1 вид и никогда не менялся.
Надеюсь, это достаточно ясно: P
Ответ 2
Так как в VaD модели представления ничего не знают о представлениях, вы можете создать полностью функционирующее приложение, полностью состоящее только из моделей просмотра и без представлений. Это приводит к возможности написания приложения, которое может полностью управляться кодом. Это, в свою очередь, приводит к возможности проведения интеграционного тестирования без GUI. Интеграционное тестирование через графический интерфейс, как известно, является хрупким - в то время как тестирование через модели просмотра должно быть более надежным.
Ответ 3
Из моего личного опыта:
Обе рабочие модели являются aviables, в зависимости от того, что вы хотите, и в зависимости от требований приложения. Идея VaD
заключается в расширении содержимого и контейнера. Если вы реализуете VaD
, вы можете использовать этот шаблон (по умолчанию), когда вы показываете какой-либо элемент этого типа. Вы можете использовать его в ItemsControls
(списки, списки, сетки и т.д.), А в ContentControls
- только привязки. Как вы сказали, VaD
работает для переключения содержимого окна с закрытием и открытием нового. Также вы можете определить представление с помощью UserControls
, тогда вы возьмете управление, если сфокусированы элементы, а также сможете управлять кодом позади. Таким образом, ваш шаблон данных может выглядеть следующим образом:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
<DataTemplate DataType="{x:Type vms:ExampleVM}" >
<CustomUserControl A="{Binding A}" B="{Binding B}" DataContext="{Binding}" .../>
</DataTemplate>
Вы также в UserControl
можете устанавливать свойства зависимостей, это упрощает работу, потому что разрешает привязки и развязывает приложение.
Но, конечно, если для приложения не требуется динамическое переключение контента, отлично использовать VaW
для главного окна или любого другого окна. Фактически вы можете использовать как VaW
, так и VaD
. Этот последний можно использовать для внутренних элементов приложения, для которых не требуются окна. Вы улучшаете то, что лучше для вас, в зависимости от требований приложения и времени, которое можно найти при разработке приложения.
Надеюсь, что этот личный опыт поможет...