全部 -
我在我的WPF应用程序中使用Unity进行DI(没有棱镜)。我有我的MainWindow.xaml和MainWindowViewModel.cs。我在Mainwindow.xaml中有一个usercontrol。用户控件有自己的uc1.xaml和uc1viewmodel.cs。 UC1 ViewModel目前作为MainWindowViewModel上的属性公开,因此我可以在usercontrol上设置datacontext(这里有很多人推荐)。
我的问题是如何/在哪里可以设置此属性 - 它是在app.xaml.cs中还是在mainwindowviewmodel的构造函数中。代码片段:
App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Step 1 - One Time - Creating an instance of the container
UnityContainer unity = new UnityContainer();
//Step 2 - Registering your MainWindowViewModel
unity.RegisterType<IViewModel, UserControl1ViewModel>();
//Step 3 - Creating an Instance
UserControl1ViewModel uc1_mwvm = unity.Resolve<UserControl1ViewModel>(); <-- doesnt help
MainWindowViewModel mwvm = unity.Resolve<MainWindowViewModel>();
MainWindow mw = unity.Resolve<MainWindow>();
mw.Show();
}
MainWindowViewModel.cs
public class MainWindowViewModel
{
public IViewModel IVM { get; set; }
public MainWindowViewModel()
{
//IVM = new UserControl1ViewModel(); <-- All I really want is an equivalent but letting Unity do the work.
}
}
MainWindow.xaml
<Window x:Class="_05_ViewFist_UC_Unity_Working.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:uc1="clr-namespace:_05_ViewFist_UC_Unity_Working"
xmlns:uc2="clr-namespace:_05_ViewFist_UC_Unity_Working"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding NNN}" />
<uc1:UC1 DataContext="{Binding UC1VM}" />
<uc2:UC2 DataContext="{Binding UC2VM}" />
</StackPanel>
</Window>
UC1
<UserControl x:Class="_05_ViewFist_UC_Unity_Working.UC1"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" >
<StackPanel Orientation="Horizontal" Background="Red">
<TextBlock Text="UC1 " />
<TextBlock Text="{Binding FirstName}" />
</StackPanel>
</UserControl>
从代码中可以看出 - UC1的实例是在xaml(MainWindow.xaml)中创建的,因此当在app.xaml.cs中创建MainWindow实例时 - 它仍然不会创建UserControl1ViewModel的实例。
再次提问:不要认为在MainwindowViewModel的构造函数中调用Unity Resolve语句是一个很好的做法。那是对的吗??
有人可以分享一下代码片段,告诉我如何/在哪里可以做到这一点?
由于
答案 0 :(得分:1)
您可以使用服务定位器模式。我将它用作Unity作为DI。
internal class ServiceLocator
{
[...]
public MainViewModel Main { get { return container.Resolve<MainViewModel>(); } }
}
您可以按照自己想要的方式对类进行实例化(DI或不是,类初始化DI或将其作为参数接收,您可以将DI存储在私有静态属性中,如果DI为null,则可以初始化类或当应用程序启动等...)。
在App.xaml中
<Application.Resources>
<vm:ServiceLocator x:Key="Locator"/>
</Application.Resources>
现在,您可以设置datacontext
DataContext="{Binding Main, Source={StaticResource Locator}}"
编辑:
我找到了另一种方法(其中包括): 看看this article。在命令中,您可以根据需要解析视图模型。
答案 1 :(得分:1)
我从github下载了你的解决方案并尝试解决你的问题。
你做得很好,只是忘了一些细节,比如财产属性。
这就是你的App.cs文件看起来很相似的方式:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Step 1 - One Time - Creating an instance of the container
UnityContainer unity = new UnityContainer();
//Step 2 - Registeration
unity.RegisterType<IMainWindowViewModel, MainWindowViewModel>();
unity.RegisterType<IUC1ViewModel, UC1ViewModel>();
unity.RegisterType<IUC2ViewModel, UC2ViewModel>();
//// Instance of MainWindowViewModel will be created once you call Resolve MainWindow.
MainWindow mw = unity.Resolve<MainWindow>();
mw.Show();
}
以下是我改变的内容:
public class MainWindowViewModel : IMainWindowViewModel
{
#region Public Properties
[Dependency]
public IUC1ViewModel UC1VM { get; set; }
[Dependency]
public IUC2ViewModel UC2VM { get; set; }
public string NNN { get; set; }
#endregion
public MainWindowViewModel()
{
NNN = "This value coming from MainWindowViewModel";
}
}
[Dependency]
是一个属性属性,告诉Unity注入值的位置。
如果你愿意,我可以将我的代码合并到github中的repo。
让我知道这是否对你有所帮助。请随意将此标记为答案。