我正在尝试在我的 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)到 ViewA
和 ViewB
,两者都使用相同的单例实例。
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/