C# 带Unity的Prism 6-无命名约定的视图解析视图模型

C# 带Unity的Prism 6-无命名约定的视图解析视图模型,c#,wpf,mvvm,unity-container,prism-6,C#,Wpf,Mvvm,Unity Container,Prism 6,我正在尝试在我的WPF应用程序中使用带Prism 6和Unity的DI解析视图模型,这是可行的。但是,我不知道如何告诉框架哪个视图应该与哪个视图模型合并 如果我使用约定,即拥有ViewModels和Views命名空间,以及类ViewA和ViewAViewModel,那么一切都可以工作,但是我希望能够更灵活地命名和组织我的类,这就是为什么我想以某种方式明确地告诉框架哪个视图与哪个视图模型相匹配。我尝试了很多东西,但都没有真正起作用。当前“解决方案”使应用程序运行,但未设置视图模型 代码如下: Vi

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

如果我使用约定,即拥有ViewModels和Views命名空间,以及类ViewA和ViewAViewModel,那么一切都可以工作,但是我希望能够更灵活地命名和组织我的类,这就是为什么我想以某种方式明确地告诉框架哪个视图与哪个视图模型相匹配。我尝试了很多东西,但都没有真正起作用。当前“解决方案”使应用程序运行,但未设置视图模型

代码如下:

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>
Model.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));
    }
}
公共类引导程序:UnityBootstrapper
{
受保护的覆盖依赖对象CreateShell()
{
返回Container.Resolve();
}
受保护的覆盖无效初始值设置Shell()
{
Application.Current.MainWindow.Show();
}
受保护的覆盖无效配置容器()
{
base.ConfigureContainer();
RegisterType(新的ContainerControlledLifetimeManager());
Container.RegisterType(“ViewA”);
}
受保护的覆盖无效配置ViewModelLocator()
{
ViewModelLocationProvider.SetDefaultViewModelFactory(类型=>Container.Resolve(类型));
}
}

这里有一个链接,指向Brian在ViewModelLocator上的博客,其中包括一个部分(更改那些讨厌的约定),介绍如何在需要时覆盖约定

就我个人而言,在视图注册到模块中的容器之后,我在UserControl的代码隐藏中,在构造函数中设置了DataContext。该死的!!:)


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

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

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

我看过那篇文章和很多其他东西,但我仍然不想要约定。我也尝试过你的方法,但问题是每当我使用
ViewA
ViewAVM
作为参数并设置其
DataContext
时,我会在
main window
方法的
InitializeComponent
中得到一个
NullReferenceException
构造函数。你可以克隆此repo并查看。我没有安装Git。如果您想让它以我的方式工作,那么您需要一个模块,以及引导程序中CreateModuleCatalog的重写。CreateModuleCatalog是注册实现IModule接口的模块的地方。在模块的Initialize方法中,向容器注册视图。容器看到视图需要一个ViewModel,并提供了一个ViewModel。这可能比你想要的或需要的更多。您可以使用DataContext=newviewavm();你看过GitHub上的PrismLibrary示例了吗?你是说要将视图模型注入视图,我需要使用模块。我不想在代码隐藏中创建VM,我决定随着项目的发展使用DI,这也允许我为xaml中定义的popupwindowaction注入服务。我看了你给出的示例,但我不知道我正在寻找模块:p我明天将看一看这个模块方法。尝试切换向容器注册对象的顺序。首先添加MV,然后添加视图。可能就这么简单。也许虚拟机会解决这个问题。胡猜!!
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));
    }
}
public ProductView(ProductViewModel view_model)
{
    InitializeComponent();
    DataContext = view_model;
}
public void BindViewModelToView<TViewModel, TView>()
{
    ViewModelLocationProvider.Register(typeof(TView).ToString(), () => Container.Resolve<TViewModel>());
}
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>();
    }
}