Перейти к основному содержимому

View Locator

к сведению

ViewLocator является опциональным и включен в стандартные шаблоны Avalonia. Вместо него можно использовать явные DataTemplates.

ViewLocator разрешает View для ViewModel в MVVM-приложениях. Он реализует IDataTemplate для сопоставления ViewModel и View типов.

Реализация по умолчанию

Реализация по умолчанию использует рефлексию. Она заменяет "ViewModel" на "View" в полном имени типа и ищет ожидаемый тип View.

Пример: MyApp.ViewModels.MainViewModelMyApp.Views.MainView

подсказка

Хотя подход на основе рефлексии является самым простым, рекомендуется реализовать собственный ViewLocator, адаптированный к вашему приложению, используя одну из приведенных ниже альтернатив для повышения производительности, типобезопасности и совместимости с AOT.

public class ViewLocator : IDataTemplate
{
public Control 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;
}
}
  • Метод Match проверяет, является ли данные экземпляром ViewModelBase
  • Метод Build создает экземпляр View с помощью рефлексии или возвращает TextBlock с ошибкой, если View не найдена

Регистрация

Зарегистрируйте ViewLocator в App.axaml:

<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyApp.App"
xmlns:local="using:MyApp"
RequestedThemeVariant="Default">
<Application.DataTemplates>
<local:ViewLocator />
</Application.DataTemplates>

<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>

После регистрации ViewLocator работает автоматически:

DataContext = new MainViewModel(); // ViewLocator разрешает в MainView

Или с привязкой данных:

<ContentControl Content="{Binding CurrentViewModel}" />

Альтернативные реализации

Сопоставление с образцом (Pattern Matching)

Типобезопасный подход без рефлексии:

public class ViewLocator : IDataTemplate
{
public Control Build(object data)
{
return data switch
{
MainViewModel vm => new MainView { DataContext = vm },
SettingsViewModel vm => new SettingsView { DataContext = vm },
_ => new TextBlock { Text = $"View not found for {data.GetType().Name}" }
};
}

public bool Match(object data) => data is ViewModelBase;
}
  • Типобезопасность на этапе компиляции и лучшая производительность
  • Совместимость с Native AOT
  • Поддержка рефакторинга в IDE

DataTemplates в XAML

Декларативное определение сопоставлений View и ViewModel:

<Application.DataTemplates>
<DataTemplate DataType="{x:Type vm:MainViewModel}">
<views:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SettingsViewModel}">
<views:SettingsView />
</DataTemplate>
</Application.DataTemplates>

См. DataTemplates коллекция.

Внедрение зависимостей / IoC

При использовании DI вы можете интегрировать ViewLocator с вашим контейнером зависимостей:

  • Сопоставление с образцом + DI: Комбинируйте сопоставление с образцом с IServiceProvider.GetRequiredService() для типобезопасного разрешения
  • Регистрация фабрик: Регистрируйте View фабрики в вашем DI-контейнере, которые вызывает ViewLocator
  • Прямое разрешение: Передайте service provider в ViewLocator (может по-прежнему требовать рефлексию, если не комбинировать с сопоставлением с образцом или генераторами исходного кода)

Выбирайте на основе того, нужно ли вам избегать рефлексии или предпочитаете более простую конфигурацию.

Генераторы исходного кода (Source Generators)

Вы можете создать собственный генератор исходного кода для генерации ViewLocator кода во время компиляции. Это обеспечивает нулевые накладные расходы во время выполнения и полную совместимость с AOT.

Подробности о создании генераторов исходного кода см. в документации Microsoft по генераторам исходного кода.

Сторонние решения

StaticViewLocator - NuGet-пакет, который автоматически обнаруживает и регистрирует View.

ViewLocatorGenerator - Пример реализации генератора исходного кода для ViewLocator (не пакет, референсная реализация).

См. также