我正在MVVM Light WPF应用程序中使用Entity Framework 6。我想将应用程序的DbContext
从MainWindow.xaml
传递到用户控件的视图模型。
用户控件的视图模型是SearchEmployeeViewModel.cs
,并具有以下构造函数:
public SearchEmployeeViewModel(MyEntities context)
{
Context = context;
// Other code...
}
MainWindow.xaml
使用这个声明用户控件,这是我在尝试中所能达到的:
<usercontrol:SearchEmployeeControl>
<ObjectDataProvider ObjectType="{x:Type data:MyEntities}">
<ObjectDataProvider.ConstructorParameters>
<data:MyEntities >
</data:MyEntities>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
</usercontrol:SearchEmployeeControl>
应用程序的DbContext
在MainViewModel.cs
构造函数中以这种方式实例化:
_context = new MyEntities();
如何通过MainWindow.xaml
将此EF DbContext
传递到SearchEmployeeViewModel.cs
构造函数?我试图做一些类似的事情,但传递整个数据上下文对象:在哪里创建参数化ViewModel?
更新:我正在尝试将EF DbContext传递给用户控件。
您标记了这个MVVM,所以这个答案将基于使用MVVM。
视图不应创建对象或尝试分配值。。。它只是用户可以用来交互的ViewModel/Models的用户友好反映。
你现在看到的是:
- AppStartup创建EF dbContext,并将其分配给View.DataContext
- View创建ViewModel,并尝试将EF dbContext传递给它
这是不正确的,因为视图不应该负责创建对象或分配类似的值。
MVVM需要
- 应用程序启动
- 创建ViewModel和EF数据库上下文
- 将dbContext设置为ViewModel
- 创建视图,并将ViewModel指定给View.DataContext
- 视图向用户显示ViewModel,并允许用户与其交互
所以你应该有这样的东西:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var app = new MainWindow();
var dbContext = new MyEntities();
var context = new MyViewModel(dbContext);
app.DataContext = context;
app.Show();
}
AppStartup负责任何类型的应用程序初始化,例如创建EF DataContext或ViewModels。
从View,你可以写一些类似的东西
<DataTemplate DataType="{x:Type local:SearchEmployeeViewModel}">
<userControl:SearchEmployeeControl />
</DataTemplate>
这将告诉WPF
每当在VisualTree中遇到
SearchEmployeeViewModel
类型的对象时,请使用SearchEmployeeControl
绘制该对象,并将该控件的DataContext
设置为SearchEmployeeViewModel
。
通常,ViewModels通过Content
或ItemsSource
属性插入到UI中,如下所示:
<ContentControl Content="{Binding SearchEmployeeViewModel}" />
<TabControl Content="{Binding TabViewModels}" />
如果你有兴趣了解更多,或者我强烈建议你阅读你所说的"DataContext"是什么?如果您是WPF的新手,但仍然不清楚DataContext是什么或它是如何工作的。
也就是说,如果你想让你的视图像你的问题中那样分配ViewModel的值,你的选择是
- 通过视图后面的代码分配属性
- 将
ViewModel.Context
更改为DependencyProperty,并使用OneWayToSource
绑定模式对其进行绑定,这意味着绑定只能通过将值从View传输到ViewModel来工作
我不推荐这两种方法,我更愿意在MVVM中重新设计以正确地做到这一点,但如果我被迫选择一种,我会选择使用代码隐藏。在这一点上,您已经违反了一系列规则,所以为什么不再违反一条呢:)
您想要这样的东西:
<usercontrol:SearchEmployeeControl>
<usercontrol:SearchEmployeeControl.DataContext>
<viewModel:SearchEmployeeViewModel>
<ViewModel:SearchEmployeeViewModel Context={Binding RelativeSource={RelativeSource AncestorType={x:Type Window}} />
</viewModel:SearchEmployeeViewModel>
</usercontrol:SearchEmployeeControl.DataContext>
</usercontrol:SearchEmployeeControl>
需要注意的重要事项是,AncestorType={x:Type Window}
应该是您的任何视图(即窗口、页面等)
此外,视图模型的声明必须在一个标记中。如果你有一个打开和关闭标签,我认为你需要使用Setter,但我没有测试