feat: MainView

This commit is contained in:
2026-04-13 09:29:03 +03:00
parent 8cf1c89863
commit 16c5b5d42f
9 changed files with 518 additions and 3 deletions
+76
View File
@@ -0,0 +1,76 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using GSS2.UI.Core.ViewModels;
namespace GSS2;
/// <summary>
/// <see cref="DependencyInjectionViewLocator"/> - интерфейс между Avalonia и механизмом DI (Dependency Injection)
/// из Microsoft.Extensions.Hosting.<br/>
/// Создаёт View для переданной ViewModel.<br/>
/// Обязательным условием его работы является, то что:
/// <list type="bullet">
/// <item>Класс <i>View</i> находится в пространстве имён <i>SomeNameSpace.Views</i> и имеет имя <i>SomeClassView</i></item>
/// <item>Класс <i>ViewModel</i> находится в пространстве имён <i>SomeNameSpace.ViewModels</i> и имеет имя <i>SomeClassViewModel</i></item>
/// <item>Класс <i>ViewModel</i> наследован от <see cref="ViewModelBase"/></item>
/// <item>Класс <i>View</i> наследован от <see cref="Control"/></item>
/// </list>
/// </summary>
public class DependencyInjectionViewLocator : IDataTemplate
{
private readonly ILogger<DependencyInjectionViewLocator> _logger;
private readonly IServiceProvider _services;
public DependencyInjectionViewLocator(ILogger<DependencyInjectionViewLocator> logger, IServiceProvider services)
{
_logger = logger;
_services = services;
}
public bool Match(object? data) => data is ViewModelBase;
public Control? Build(object? data)
{
// Если data - null или каким-то образом не ViewModelBase, то возвращаем null
if (data is not ViewModelBase viewModel)
return null;
// Получаем имя класса ViewModel с полным описанием сборки
var viewModelName = viewModel.GetType().AssemblyQualifiedName;
if (viewModelName is null)
{
_logger.LogError("Не удалось получить имя класса ViewModel: {}", viewModel);
return new Control();
}
// Заменяем ".ViewModel" на ".View" в имени класса ViewModel и получаем имя класса View и его тип
var viewName = viewModelName.Replace("ViewModel", "View");
var viewType = Type.GetType(viewName);
if (viewType is null)
{
_logger.LogError("Не удалось найти класс View \"{}\"", viewName);
return new Control();
}
// Ищем тип View в сервисах
var view = _services.GetService(viewType);
if (view is null)
{
_logger.LogError("Класс View \"{}\" не зарегистрирован", viewName);
return new Control();
}
if (view is not Control control)
{
_logger.LogError("Класс View \"{}\" не наследован от Control", viewName);
return new Control();
}
control.DataContext = viewModel;
return control;
}
}