WPF MVVM Навіщо використовувати подання ContentControl + DataTemplate, а не прямі перегляди вікон XAML?


83

Чому це?

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: (встановити вікно запуску / перегляд)

<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: (вікно, а не ресурсний словник)

<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>

По суті, це "Переглянути як шаблон даних" (VaD) проти "Переглянути як вікно" (VaW)

Ось моє розуміння порівняння:

  • VaD: Дозволяє перемикати подання, не закриваючи вікно. (Це не бажано для мого проекту)
  • VaD: VM абсолютно нічого не знає про View, тоді як у VaW він (лише) повинен мати можливість створити його при відкритті іншого вікна
  • VaW: Я фактично бачу, як мій xaml відображається в конструкторі (я не можу з VaD, принаймні в моїй поточній установці)
  • VaW: працює інтуїтивно з відкриванням і закриванням вікон; кожне вікно має (є) відповідний вигляд (і ViewModel)
  • VaD: ViewModel може проходити по початковій ширині вікна, висоті, зміні розміру тощо через властивості (тоді як у VaW вони встановлюються безпосередньо у Вікні)
  • VaW: може встановити FocusManager.FocusedElement (не знаю, як у VaD)
  • VaW: Менше файлів, оскільки мої типи вікон (наприклад, стрічка, діалогове вікно) включені в їх подання

То що тут відбувається? Чи не можу я просто побудувати свої вікна в XAML, отримати доступ до їх даних чисто через властивості віртуальної машини і закінчити з цим? Код позаду той самий (практично нульовий).

Я намагаюся зрозуміти, чому я повинен перемішувати всі матеріали View у ResourceDictionary.


2
Подумайте так: ViewModels відображатимуться у Windows або UserControls. Poco повинні відображатися в DataTemplates. :)
dev hedgehog

Відповіді:


130

Люди використовують DataTemplatesтакий спосіб, коли хочуть динамічно перемикати подання залежно від 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 подання і ніколи не змінюється.


8

Оскільки у VaD моделі перегляду нічого не знають про погляди, ви можете створити повністю функціонуючу програму, повністю складену лише з моделей перегляду, без переглядів. Це призводить до можливості написання програми, яка може повністю керуватися кодом. Це, в свою чергу, призводить до можливості проведення інтеграційного тестування без графічного інтерфейсу користувача. Тестування інтеграції за допомогою графічного інтерфейсу користується загальновизнаною крихкістю - тоді як тестування через моделі представлення повинно бути більш надійним.


5

З мого особистого досвіду: обидві моделі роботи доступні залежно від того, що ви хочете, і залежно від вимог програми. Ідея 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. Цей останній можна використовувати для внутрішніх елементів програми, для яких не потрібні вікна. Ви визначаєте, що для вас краще, залежно від вимог програми та часу, необхідного для розробки програми. Сподіваюся, цей особистий досвід допоможе ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.