📄 src/App/ViewLocator.cs
using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Microsoft.Extensions.DependencyInjection;
using MMirror.App.ViewModels;
using MMirror.App.ViewModels.Panels;
using MMirror.App.Views;
using MMirror.App.Views.Panels;

namespace MMirror.App;

/// <summary>
/// Given a view model, returns the corresponding view if possible.
/// </summary>
public class ViewLocator(IServiceProvider services) : IDataTemplate
{
    public Control Build(object? data) =>
        data switch
        {
            MainViewModel => services.GetControlOrDefault<MainView>(),
            DateTimePanelViewModel => services.GetControlOrDefault<DateTimePanel>(),
            VasttrafikPanelViewModel => services.GetControlOrDefault<VasttrafikPanel>(),
            _ => new TextBlock { Text = $"No view for {data?.GetType().Name}" },
        };

    public bool Match(object? data) => data is ViewModelBase;
}

file static class ViewLocatorServiceProviderExtensions
{
    extension(IServiceProvider services)
    {
        public Control GetControlOrDefault<T>()
            where T : Control =>
            services.GetService<T>() ?? (Control)new TextBlock { Text = $"No view for type {typeof(T).Name}" };
    }
}