WinUI - 依赖注入和 Window 导航

WinUI - Dependency Injection and Window Navigation

我正在尝试了解如何正确使用依赖注入来导航到我的应用程序中的不同页面。目前只有一个 Main Window 和一个 Login Window。既然我的 Windows 存储在 NavigationService._windows 中,我该如何创建/访问那个 window 的实例?

感谢您的帮助。

这是App.xaml.cs中的相关代码:

    protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs e)
    {
        Container = RegisterServices();

        _loginWindow = new LoginWindow();
        _loginWindow.Activate();
    }

    private IServiceProvider RegisterServices()
    {
        var services = new ServiceCollection();
        var navigationService = new NavigationService();

        // Register Windows:
        navigationService.Configure(nameof(LoginWindow), typeof(LoginWindow));
        navigationService.Configure(nameof(MainWindow), typeof(MainWindow));

        services.AddSingleton<INavigationService>(navigationService);

        // Register ViewModels:
        services.AddTransient<LoginViewModel>();
        services.AddSingleton<MainViewModel>();

        return services.BuildServiceProvider();
    }

这是我的 NavigationService class 其中两个 windows 注册到:

public class NavigationService : INavigationService
{
    private readonly IDictionary<string, Type> _windows = new ConcurrentDictionary<string, Type>();
    // Interface Implementation
    public string CurrentWindow => throw new NotImplementedException();

    public void GoBack()
    {
        throw new NotImplementedException();
    }

    public void NavigateTo(string window, object parameter = null)
    {
        if (!_windows.ContainsKey(window))
        {
            throw new ArgumentException($"Unable to find a page registered with the name {window}.");
        }

        // Code to navigate to window should go here...
        // this is where I'm a bit stuck.
        throw new NotImplementedException();
    }

    // Class Functions:
    public void Configure(string window, Type type)
    {
        if (_windows.Values.Any(v => v == type))
        {
            throw new ArgumentException($"The {type.Name} view has already been registered under another name.");
        }

        _windows[window] = type;
    }
}

我不清楚您提供的代码是如何在您的应用程序中使用 DI 的。但这是我一直在使用的一种方法:

public partial class App : Application
{
    public new static App Current => (App)Application.Current;

    public IJ4JHost Host { get; }

    public App()
    {
        this.InitializeComponent();

        var hostConfig = new J4JHostConfiguration()
                        .Publisher( "J4JSoftware" )
                        .ApplicationName( "GPSLocator" )
                        .LoggerInitializer( InitializeLogger )
                        .AddNetEventSinkToLogger()
                        .AddDependencyInjectionInitializers( SetupDependencyInjection )
                        .AddServicesInitializers( InitializeServices )
                        .AddUserConfigurationFile( "userConfig.json", optional: true, reloadOnChange: true )
                        .AddApplicationConfigurationFile( "appConfig.json", optional: false )
                        .FilePathTrimmer( FilePathTrimmer );

        if (hostConfig.MissingRequirements != J4JHostRequirements.AllMet)
            throw new ApplicationException($"Missing J4JHostConfiguration items: {hostConfig.MissingRequirements}");

        Host = hostConfig.Build()
         ?? throw new NullReferenceException($"Failed to build {nameof(IJ4JHost)}");
    }
}

无需深入了解我的主机配置构建器的工作原理,基本上它有一个 DI 设置组件(以及其他一些东西,如日志记录和命令行处理),您可以通过 Services 属性 曝光于 IJ4JHost.

此设置实质上使 App class 成为视图模型定位器,如果该术语对您有意义的话。

例如,如果我在某处需要一个特定视图模型的实例,我会这样获取它:

Configuration = App.Current.Host.Services.GetRequiredService<AppConfig>();

如果您想了解有关我的主机构建器如何工作的更多详细信息,您可以查看其 github repository。它位于 DependencyInjection 项目文件夹中。

您可以在我写的 github repository for a GPS locator app 中看到我如何实际使用它的示例。