通过XAML将DB上下文传递给用户控件的VM

时间:2016-03-31 13:13:11

标签: c# wpf entity-framework xaml mvvm

我在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();

如何通过DbContext将此EF SearchEmployeeViewModel.cs传递给MainWindow.xaml构造函数?我正在尝试做类似的事情,但传递整个数据上下文对象:Where to create parametrized ViewModel?

更新:我正在尝试将 EF DbContext 传递给用户控件。

2 个答案:

答案 0 :(得分:7)

您使用此MVVM进行了标记,因此这个答案将基于使用MVVM。

View不应该创建对象或尝试分配值...它只是用户友好地反映用户可以用来与之交互的ViewModel / Models。

你现在看到的是:

  • AppStartup创建EF dbContext,并将其分配给View.DataContext
  • View创建ViewModel,并尝试将其传递给EF dbContext

这是不正确的,因为View不应该负责创建对象或分配像这样的值。

你想要的MVVM是什么

  • AppStartup
    • 创建ViewModel和EF dbContext
    • 将dbContext设置为ViewModel
    • 创建视图,并将ViewModel指定给View.DataContext
  • View向用户显示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

通常,ViewModel通过ContentItemsSource属性插入到用户界面中,如下所示:

<ContentControl Content="{Binding SearchEmployeeViewModel}" />

<TabControl Content="{Binding TabViewModels}" />

如果您有兴趣了解更多信息,我也有Simple MVVM Example on my blog,或者如果您对WPF不熟悉,我仍强烈建议您阅读What is this "DataContext" you speak of?,但仍然不了解DataContext是什么或它是如何工作的。

也就是说,如果您想让View分配ViewModel的值,那么您的选项就是

  • 通过视图背后的代码
  • 分配属性
  • ViewModel.Context更改为DependencyProperty,并使用OneWayToSource绑定模式绑定它,这意味着绑定只能通过将值从View传输到ViewModel来实现。

我不推荐其中任何一个,而是宁愿重新设计在MVVM中正确地执行此操作,但是如果我被迫选择一个,我会选择使用代码。你现在已经打破了一堆规则,所以为什么不再这样做了:))

答案 1 :(得分:0)

你想要这样的东西:

<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}应该是您的观点(即Window,Page等)。

此外,您的viewmodel声明必须位于单个标记中。如果你有一个开始和结束标签我认为你需要使用Setter但我没有测试