c# - 带有 Unity 的 Prism 6 - 在没有命名约定的情况下解析 View 的 View 模型

标签 c# wpf mvvm unity-container prism-6

我正在尝试在我的 WPF 应用程序中使用 DI 与 Prism 6 和 Unity 解析 View 模型,这很有效。但是我不知道如何告诉框架应该将哪个 View 与哪个 View 模型合并。

如果我使用约定,即有 ViewModels、Views 命名空间以及 ViewA 和 ViewAViewModel 类,一切正常,但是我想更灵活地命名和组织我的类,这就是为什么我想以某种方式告诉框架明确哪个 View 与哪个 View 模型一起使用。我尝试了很多东西,但没有任何效果。当前的“解决方案”使应用程序运行但未设置 View 模型。

代码如下:

ViewA.xaml

<UserControl x:Class="WPFDITest.Views.ViewA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel>
        <TextBlock Text="{Binding ViewAMessage}"/>
        <TextBox Text="{Binding ViewAMessage, UpdateSourceTrigger=PropertyChanged}"/>
    </StackPanel>
</UserControl>

主窗口.xaml

<UserControl x:Class="WPFDITest.Views.ViewA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel>
        <TextBlock Text="{Binding ViewAMessage}"/>
        <TextBox Text="{Binding ViewAMessage, UpdateSourceTrigger=PropertyChanged}"/>
    </StackPanel>
</UserControl>

ViewAVM.cs

public class ViewAVM : BindableBase
{
    private string viewAMessage;

    public ViewAVM(IModelA model)
    {
        viewAMessage = model.HelloMsgA();
    }

    public string ViewAMessage
    {
        get { return viewAMessage; }
        set { SetProperty(ref viewAMessage, value); }
    }
}

模型.cs

public interface IModelA
{
    string HelloMsgA();
}

public class ModelA : IModelA
{
    public string HelloMsgA()
    {
        return "Hello from A!";
    }
}

App.xaml.cs

public partial class App
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var bootstraper = new Bootstrapper();
        bootstraper.Run();
    }
}

Bootstrapper.cs

public class Bootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void InitializeShell()
    {
        Application.Current.MainWindow.Show();
    }

    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();
        Container.RegisterType<IModelA, ModelA>(new ContainerControlledLifetimeManager());
        Container.RegisterType<object, ViewAVM>("ViewA");
    }

    protected override void ConfigureViewModelLocator()
    {
        ViewModelLocationProvider.SetDefaultViewModelFactory(type => Container.Resolve(type));
    }
}

最佳答案

在对 Prism 资源进行一些挖掘之后,我发现了如何做我想做的事情。我可以使用 ViewModelLocationProvider.Register 注册每个 View ,并传入 View 模型的工厂方法。我创建了使用方便的语法并使用容器来解析给定类型的 View 模型的方法:

public void BindViewModelToView<TViewModel, TView>()
{
    ViewModelLocationProvider.Register(typeof(TView).ToString(), () => Container.Resolve<TViewModel>());
}

还有我如何使用它来将 ViewAVM 绑定(bind)到 ViewAViewB,两者都使用相同的单例实例。

public class Bootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void InitializeShell()
    {
        Application.Current.MainWindow.Show();
    }

    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();
        Container.RegisterType<IModelA, ModelA>(new ContainerControlledLifetimeManager());
        Container.RegisterType<ViewAVM>(new ContainerControlledLifetimeManager());
    }

    protected override void ConfigureViewModelLocator()
    {
        BindViewModelToView<ViewAVM, ViewA>();
        BindViewModelToView<ViewAVM, ViewB>();
    }
}

顺便说一句,据我所知,只有通过注册工厂或使用他们的或自定义约定,才能将 View 与 View 模型通过 ViewModelLocator 关联起来,不要寻找一些 DI 魔法。

关于c# - 带有 Unity 的 Prism 6 - 在没有命名约定的情况下解析 View 的 View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37036930/

相关文章:

c# - 仅允许 NumericUpAndDown 中的整数值 Mahapp 无法正常工作

c# - 释放 WPF 图像控件的缓存

wpf - 使 WPF 中的列表框项目不可选择

c# - 在OnNavigatedToAsync中实例化LocationService导致应用挂起

c# - 当 ItemsSource 更改时 ComboBox 不更新

c# - 使用 WinForms 的 Entity Framework UI 验证

c# - Unity ICallHandler 与 IInterceptionBehavior

c# - 如何使用 mvvm 禁用文本 block ?

c# - Gridview EditItemTemplate DropDownList 获取 SelectedValue

c# - 如何在 C# SDK 中为具有工作负载身份的 GCS 生成签名 URL?