Документация по Avalonia UI
< Все темы
Печать

Создание Model и ViewModel

Теперь, когда у нас есть основное представление на экране, давайте подумаем, как мы могли бы отобразить в нем реальные данные из базы данных или чего-то подобного. Самый очевидный и традиционный способ сделать это — загрузить данные в конструктор представления и создать CheckBox для каждого элемента TODO в коде. Однако такой способ имеет несколько недостатков:

  • Мы не можем использовать XAML
  • Мы должны написать код, чтобы реагировать на изменения в данных и обновлять отображение.
  • Это не подлежит модульному тестированию

Эти соображения могут показаться не важными для небольшого приложения, но по мере роста вашего приложения они становятся все более и более серьезными проблемами: особенно в части тестируемости.

Существует лучший способ! Мы упомянули шаблон MVVM в начале этого руководства, и именно его мы собираемся использовать сейчас.

Создайте модель

Первое, что нужно сделать, это создать модель, которая будет представлять наши данные так, как они будут храниться в базе данных. Наша модель будет довольно простой: каждый элемент TODO будет состоять из текстового описания и логического значения, указывающего, отмечен ли этот элемент.

Поместите следующий класс в каталог Models вашего проекта:
Models/TodoItem.cs

namespace Todo.Models
{
    public class TodoItem
    {
        public string Description { get; set; }
        public bool IsChecked { get; set; }
    }
}
Создайте (поддельную) базу данных

Мы могли бы использовать что-то вроде Entity Framework для чтения этих данных из базы данных SQLite, но поскольку это учебник по Avalonia, а не Entity Framework, мы на самом деле не будем использовать базу данных. Вместо этого мы просто заполним наши модели из массива.

Мы сделаем это в сервисе под названием Database и поместим его в каталог Services:
Services/Database.cs

using System.Collections.Generic;
using Todo.Models;

namespace Todo.Services
{
    public class Database
    {
        public IEnumerable<TodoItem> GetItems() => new[]
        {
            new TodoItem { Description = "Walk the dog" },
            new TodoItem { Description = "Buy some milk" },
            new TodoItem { Description = "Learn Avalonia", IsChecked = true },
        };
    }
}
Создайте модель представления

Теперь нам понадобится модель представления, представляющая список. Это класс, который будет предоставлять данные для нашего представления.

Мы уже создали представление и назвали его TodoListView, поэтому связанная модель представления будет называться TodoListViewModel. Поместите этот класс в каталог ViewModels в вашем проекте:
ViewModels/TodoListViewModel.cs

using System.Collections.Generic;
using System.Collections.ObjectModel;
using Todo.Models;

namespace Todo.ViewModels
{
    public class TodoListViewModel : ViewModelBase
    {
        public TodoListViewModel(IEnumerable<TodoItem> items)
        {
            Items = new ObservableCollection<TodoItem>(items);
        }

        public ObservableCollection<TodoItem> Items { get; }
    }
}

Опять же, наша модель представления на данном этапе очень проста. Он просто берет коллекцию моделей TodoItem в своем конструкторе и помещает их в ObservableCollection, которая доступна через свойство Items.

Следует обратить внимание на использование класса ViewModelBase. Важность этого станет ясна в ближайшее время.

Создайте экземпляр TodoListViewModel

Мы видели, что наша модель TodoListViewModel требует, чтобы коллекция моделей TodoItem передавалась ее конструктору, но откуда берутся эти элементы? Где создается TodoListViewModel?

Что ж, теперь у нас есть два представления и две модели представлений:

  • MainWindow (создается по шаблону)
  • MainWindowViewModel (создается по шаблону)
  • TodoListView (создано нами)
  • TodoListViewModel (создано нами)

Если вы вспомните, когда мы создавали представления, вы помните, что наши представления имеют отношение родитель-потомок (TodoListView является дочерним элементом MainWindow). Это может дать нам подсказку: MainWindowViewModel должен создать TodoListViewModel!

Отредактируйте файл MainWindowViewModel.cs следующим образом:
MainWindowViewModel.cs

using Todo.Services;

namespace Todo.ViewModels
{
    class MainWindowViewModel : ViewModelBase
    {
        public MainWindowViewModel(Database db)
        {
            List = new TodoListViewModel(db.GetItems());
        }

        public TodoListViewModel List { get; }
    }
}

Наконец, отредактируйте метод OnFrameworkInitializationCompleted в App.axaml.cs, чтобы создать экземпляр базы данных и передать его в MainWindowViewModel:

public override void OnFrameworkInitializationCompleted()
{
    base.OnFrameworkInitializationCompleted();

    if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
    {
        var db = new Database();

        desktop.MainWindow = new MainWindow
        {
            DataContext = new MainWindowViewModel(db),
        };
    }
}

Далее мы собираемся подключить представления для чтения из наших моделей представлений…

Оглавление