MVVM

Паттерн Model-View-ViewModel

Последнее обновление: 24.01.2023

Паттерн Model-View-ViewModel (MVVM) основывается на разделении функциональной части приложения на три ключевых компонента:

  • View - представление или пользовательский интерфейс

  • Model - модель или данные, которые используются в приложении

  • ViewModel - промежуточный слой между представлением и данными, который обеспечивает их взаимодействие

Преимуществом использования данного паттерна является меньшая связанность между компонентами и разделение ответственности между ними. То есть Model отвечает за данные, View отвечает за графический интерфейс, а ViewModel - за логику приложения.

Легкость реализации паттерна MVVM в .NET MAUI и C# стала возможной благодаря встроенному механизму привязки. Как правило, через свойство BindingContext визуального элемента устанавливается объект ViewModel. Далее через этот ViewModel идут все взаимодействия между данными и визуальным интерфейсом.

Рассмотрим простейший пример. Определим класс данных или модели:

public class Person
{
    public string Name { get; set; } = "";
    public int Age { get; set; }
}

Также добавим в проект класс, который назовем PersonViewModel со следующим содержимым:

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace HelloApp;

public class PersonViewModel : INotifyPropertyChanged
{
    Person person = new Person{Name="Tom", Age=38};

    public event PropertyChangedEventHandler? PropertyChanged;

    public string Name
    {
        get => person.Name;
        set
        {
            if (person.Name != value)
            {
                person.Name = value;
                OnPropertyChanged();
            }
        }
    }
    public int Age
    {
        get => person.Age;
        set
        {
            if (person.Age != value)
            {
               person.Age = value;
                OnPropertyChanged();
            }
        }
    }
    public void OnPropertyChanged([CallerMemberName] string prop = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
    }
}

Это и будет компонент ViewModel, который связывает данные и визуальный интерфейс. По большому счету она представляет обертку над классом Person, определяя все те же свойства. Для упрощения задачи сам объект Person задается непосредственно в классе в качестве глобальной переменной, хотя в реальности там могла бы быть более сложная логика, например, по получению объекта из базы данных, из файла, из сетевого запроса и т.д..

Обычно класс ViewModel реализует интерфейс INotifyPropertyChanged, что позволяет уведомлять систему об изменении его свойств с помощью события PropertyChanged.

Теперь создадим визуальную часть. Определим на главной странице MainPage.xaml следующее содержимое:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloApp.MainPage">
    <VerticalStackLayout Padding="5">
        <Label Text="Name" />
        <Label Text="{Binding Name}" FontAttributes="Bold" />
        <Label Text="Age" />
        <Label Text="{Binding Age}" FontAttributes="Bold" />
    </VerticalStackLayout>
</ContentPage>

Здесь определена привязка к свойствам ViewModel.

А в конструкторе страницы в файле кода MainPage.xaml.cs пропишем в качестве контекста данных для страницы определенную ранее ViewModel:

namespace HelloApp;

public partial class MainPage : ContentPage
{
    public MainPage()
	{
		InitializeComponent();
        // привязка к ViewModel
        BindingContext = new PersonViewModel();
    }
}

И при запуске приложение выведет нам все данные о viewmodel, переданной во view:

Паттерн MVVM в .NET MAUI и C#

При использовании паттерна в качестве представления обычно выступает страница, и, как правило, одно представление (одна страница) связана с одной моделью представления (ViewModel). При этом одну и ту же VıewModel могут использовать несколько представлений.

Стоит отметить, что в этом отношении ViewModel ничего не знает о представлении, что это, какие элементы управления оно содержит. ViewModel только определяет логику обработку без какой-либо связи с графическим интерфейсом.

Для подобным очень простых сценариев вряд ли потребуется определять дополнительную сущность в виде ViewModel, так как проще привязать элементы управления неспосредственно к свойствам объекта Person. Однако на дальней дистанции при развитии приложения это может помочь в более структурной организации логики приложения и упрощении работы по его развитию и поддержке.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850