Поиск представлений
Подожди, отмотай на секунду назад. Внимательный читатель заметит, что в последнем разделе происходит что-то странное.
Views/MainWindow.axaml
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Todo.Views.MainWindow" Icon="/Assets/avalonia-logo.ico" Width="200" Height="300" Title="Avalonia Todo" Content="{Binding List}"> </Window>
Мы привязали свойство Window.Content
к свойству MainWindowViewModel.List
, которое является экземпляром TodoListViewModel
, но в окне отображается TodoListView
! Что тут происходит? Как отображается представление, когда содержимое окна является моделью представления?
Ответ можно найти в файле ViewLocator.cs
, добавленном шаблоном:
ViewLocator.cs
using System; using Avalonia.Controls; using Avalonia.Controls.Templates; using Todo.ViewModels; namespace Todo { public class ViewLocator : IDataTemplate { public bool SupportsRecycling => false; public IControl Build(object data) { var name = data.GetType().FullName.Replace("ViewModel", "View"); var type = Type.GetType(name); if (type != null) { return (Control)Activator.CreateInstance(type); } else { return new TextBlock { Text = "Not Found: " + name }; } } public bool Match(object data) { return data is ViewModelBase; } } }
ViewLocator
определяет шаблон данных, который преобразует модели представлений в представления. Он определяет два метода:
Match(object data)
просматривает данные, и если данные наследуются отViewModelBase
, он возвращаетtrue
, указывая на то, что следует вызыватьBuild
.Build(object data)
принимает полное имя типа данных и заменяет строку"ViewModel"
строкой"View"
. Затем он пытается получить тип, соответствующий этому имени. Если соответствующий тип найден, он создает экземпляр типа и возвращает его.
Экземпляр ViewLocator
присутствует в Application.DataTemplates
:
<Application xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:Todo" x:Class="Todo.App"> <Application.DataTemplates> <local:ViewLocator/> </Application.DataTemplates> <Application.Styles> <StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/> <StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/> </Application.Styles> </Application>
Когда для экземпляра ContentControl (например, Window
) для свойства Content
задано значение, не являющееся элементом управления, он ищет в дереве элементов управления шаблон DataTemplate
, соответствующий данным содержимого. Если никакой другой DataTemplate
не соответствует данным, он в конечном итоге достигнет ViewLocator
в шаблонах данных приложения, который сделает свое дело и вернет экземпляр соответствующего представления.
ViewLocator
включен в исходный код проекта, а не является компонентом самой Avalonia, поскольку механизм связывания модели представления с представлением может зависеть от приложения; например, можно реализовать его с помощью инфраструктуры DI.ViewLocator
можно рассматривать как реализацию парадигмы соглашения по конфигурации.