Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Модель-View-ViewModel (MVVM) — это архитектурный шаблон пользовательского интерфейса, который отделяет пользовательский интерфейс и непользовательский код. Узнайте, как MVVM позволяет свободно сцепляться с помощью привязки данных в XAML для синхронизации пользовательского интерфейса и данных, повышения удобства обслуживания и снижения зависимостей.
Так как она обеспечивает свободное взаимодействие, использование привязки данных уменьшает жесткие зависимости между различными типами кода. Этот подход упрощает изменение отдельных единиц кода (методов, классов, элементов управления и т. д.), не вызывая непреднамеренные побочные эффекты в других единицах. Это разделение является примером разделения проблем, что является важной концепцией во многих шаблонах проектирования.
Подсказка
Когда следует использовать MVVM: Используйте MVVM для приложений с сложными потоками данных, несколькими экранами или базами кода, разработанными командой. Для простых одностраничных инструментов или прототипов код в файле отделённого кода вполне допустим — вы можете переходить на MVVM постепенно, по мере роста сложности. Если в вашем приложении есть бизнес-логика, пригодная для модульного тестирования, MVVM позволяет тестировать эту логику без запуска пользовательского интерфейса.
Преимущества MVVM
Декуплирование вашего кода имеет множество преимуществ, в том числе:
- Включение итеративного и исследовательского стиля написания кода. Изменение, изолированное, менее рискованно и проще экспериментировать.
- Упрощение модульного тестирования. Можно протестировать единицы кода, изолированные друг от друга по отдельности и за пределами рабочих сред.
- Поддержка совместной работы группы. Отдельные лица или команды могут разрабатывать несоединенный код, который соответствует хорошо разработанным интерфейсам и интегрирует его позже.
- Повышение удобства обслуживания. Исправление ошибок в развязанном коде с меньшей вероятностью вызовет регрессии в другом коде.
В отличие от MVVM, приложение с более традиционной структурой "code-behind" обычно использует привязку данных для отображаемых данных. Он реагирует на входные данные пользователей путем непосредственной обработки событий, предоставляемых элементами управления. Обработчики событий реализуются в файлах программной части (например, MainWindow.xaml.cs) и часто тесно связаны с элементами управления. Обычно они содержат код, который управляет пользовательским интерфейсом напрямую. Эта структура затрудняет или невозможно заменить элемент управления, не обновляя код обработки событий. В этой архитектуре файлы программной части часто накапливают код, который не связан с пользовательским интерфейсом, например код доступа к базе данных, который в конечном итоге дублируется и изменяется для использования с другими окнами.
Уровни приложений
При использовании шаблона MVVM приложение делится на следующие уровни:
- Уровень модели определяет типы, представляющие бизнес-данные. Этот уровень включает все необходимые для моделирования домена основного приложения и часто включает в себя основную логику приложения. Этот слой полностью не зависит от уровней представления и модели представления и часто находится частично в облаке. Учитывая полностью реализованный уровень модели, можно создать несколько различных клиентских приложений, например пакет SDK для приложений Windows и веб-приложения, которые работают с одинаковыми базовыми данными.
- Слой представления определяет пользовательский интерфейс с помощью разметки XAML. Разметка включает выражения привязки данных (например , x:Bind), определяющие соединение между определенными компонентами пользовательского интерфейса и различными элементами модели представления и модели. Иногда файлы кода можно использовать как часть слоя представления, чтобы содержать дополнительный код, необходимый для настройки пользовательского интерфейса или для извлечения данных из аргументов обработчика событий перед вызовом метода модели представления, выполняющего работу.
- Уровень модели представления предоставляет целевые объекты привязки данных для представления. Во многих случаях модель представления предоставляет модель напрямую или предоставляет элементы, которые упаковывают определенные члены модели. Модель представления также может определять элементы для отслеживания данных, относящихся к пользовательскому интерфейсу, но не к модели, например порядок отображения списка элементов. Модель представления также служит точкой интеграции с другими службами, такими как код доступа к данным. Для простых проектов может не потребоваться отдельный уровень модели, а только модель представления, которая инкапсулирует все необходимые данные.
Базовый и расширенный MVVM
Как и в любом шаблоне проектирования, существует несколько способов реализации MVVM, и многие различные методы считаются частью MVVM. По этой причине существует несколько разных сторонних платформ MVVM, поддерживающих различные платформы на основе XAML, включая пакет SDK для приложений Windows. Однако эти платформы обычно включают несколько служб для реализации развязанной архитектуры, что делает точное определение MVVM несколько неоднозначным.
Хотя сложные платформы MVVM могут быть очень полезными, особенно для проектов корпоративного масштаба, обычно существует стоимость, связанная с принятием любого конкретного шаблона или метода, и преимущества не всегда понятны, в зависимости от масштаба и размера проекта. К счастью, вы можете принять только те методы, которые обеспечивают четкое и ощутимое преимущество, и игнорировать других, пока вы не хотите их.
В частности, вы можете получить много преимуществ, просто понимая и применяя полную мощность привязки данных и разделяя логику приложения на слои, описанные ранее. Это можно достичь только с помощью возможностей, предоставляемых пакетом SDK для приложений Windows, и без использования внешних платформ. В частности, расширение разметки {x:Bind} упрощает и более высокую производительность привязки данных, чем на предыдущих платформах XAML, что устраняет необходимость большого количества стандартного кода, необходимого ранее.
Дополнительные рекомендации по использованию MVVM см. в библиотеке CommunityToolkit MVVM, которая предоставляет базовые классы, такие как ObservableObject и RelayCommand, а также генераторы исходного кода (через атрибуты [ObservableProperty] и [RelayCommand]), которые устраняют шаблонный код.
Коллекция WinUI также демонстрирует привязку данных и шаблоны MVVM с WinUI 3.
Пример CommunityToolkit.Mvvm
В следующем примере показана полная модель представления с использованием генераторов исходного кода CommunityToolkit.Mvvm 8.x. Атрибут [ObservableProperty] создает свойство и уведомление об изменении и [RelayCommand] создает реализацию ICommand :
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class CustomerViewModel : ObservableObject
{
private readonly ICustomerService _customerService;
public CustomerViewModel(ICustomerService customerService)
{
_customerService = customerService;
}
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(SaveCommand))]
private string _name = string.Empty;
[ObservableProperty]
private bool _isBusy;
[RelayCommand(CanExecute = nameof(CanSave))]
private async Task SaveAsync()
{
IsBusy = true;
await _customerService.SaveAsync(Name);
IsBusy = false;
}
private bool CanSave() => !string.IsNullOrWhiteSpace(Name);
}
Привязать этот ViewModel к странице с помощью {x:Bind}:
<Page x:Class="MyApp.Views.CustomerPage"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Save" Command="{x:Bind ViewModel.SaveCommand}" />
<ProgressRing IsActive="{x:Bind ViewModel.IsBusy, Mode=OneWay}" />
</StackPanel>
</Page>
В скрытом коде страницы предоставляется свойство ViewModel, на которое ссылается {x:Bind}:
// CustomerPage.xaml.cs
public sealed partial class CustomerPage : Page
{
public CustomerViewModel ViewModel { get; }
public CustomerPage()
{
// Resolve via DI; see Architecture patterns for WinUI 3 desktop apps
// for how to configure App.GetService<T>() with Microsoft.Extensions.DependencyInjection.
ViewModel = App.GetService<CustomerViewModel>();
InitializeComponent();
}
}
Рекомендации по объединению MVVM с внедрением зависимостей, конфигурацией и корпоративными шаблонами см. в шаблонах архитектуры классических приложений WinUI 3.
См. также
Темы
Подробная привязка данных
Расширение разметки {x:Bind}
Советы по производительности MVVM для приложений WinUI
Шаблоны архитектуры для классических приложений WinUI 3
Ресурсы WinUI 3 и MVVM
Документация CommunityToolkit MVVM
Коллекция WinUI — примеры привязки данных
Template Studio для WinUI
Windows developer