如何在WPF EF MVVM中重复使用Entity Framework数据源

3

你好,我正在使用WPF4、EF和MVVM设计一个应用程序。我想创建可重复使用的UserControl,可以在应用程序的多个窗口中使用,并且从相同的数据源中提取数据。

假设我有一个GraphView组件和一个TableView组件,它们可以出现在同一页上或者应用程序的不同位置,我希望它们都反映出过滤后的EF实体集。MVVM的通常做法似乎要求每个视图都有自己的viewmodel。但是,我应该使用联合viewmodel,将两个绑定到它上面,这样如果你更改数据或筛选条件,两个都会同时更新吗?如果不是,我该如何处理?

谢谢任何建议!

4个回答

2
根据我在使用EF四天后的了解,你的EF类位于项目级别。我的第一反应是实现一个单例,其中包含对你希望在视图模型之间共享的实体的引用。当然,这将创建对单例的类依赖关系。
事实上,这听起来像是Unity、MEF或其他能够进行依赖注入的框架所解决的设计问题。你可以将EF类放在这些框架中的一个模块中,并使用它们的协议来协调EF和你的VM。然后,在EF中更改过滤器或数据时,也会触发VM可以注册接收的消息,以触发UI更改或VM状态更改等操作。

2

一种方法是拥有两个ViewModel,一个用于每个View / UserControl,然后将它们嵌套到某个顶层或更高级别的ViewModel中。例如,如果两个视图都驻留在MainWindow视图中,则可能如下所示:

public class MainWindowViewModel
{
    public MainWindowViewModel(IRepository repository)
    {
        SharedUserControlData sharedData = new SharedUserControlData()
        {
           MyCollection = new ObservableCollection<MyEntity>(
               repository.GetMyEntities()),
           // instantiate other shared data properties
        }

        UserControl1ViewModel = new UserControl1ViewModel(sharedData);
        UserControl2ViewModel = new UserControl2ViewModel(sharedData);
    }

    public UserControl1ViewModel UserControl1ViewModel { get; private set; }
    public UserControl2ViewModel UserControl2ViewModel { get; private set; }

    // more stuff...
}

您有一个SharedUserControlData类,其中包含两个视图都可以绑定到的属性:

public class SharedUserControlData : INotifyPropertyChanged
{
    public ObservableCollection<MyEntity> MyCollection { get; set; }
    // other properties
    // INotifyPropertyChanged implementation
}

用户控件的ViewModel会注入这些数据:

public class UserControl1ViewModel
{
    public UserControl1ViewModel(SharedUserControlData data)
    {
        SharedUserControlData = data;
    }

    public SharedUserControlData SharedUserControlData { get; private set; }

    // more stuff
}

// and the same for UserControl2ViewModel

您的用户控件视图通过DataTemplate与ViewModel绑定:
<DataTemplate DataType="{x:Type vm:UserControl1ViewModel}" >
    <v:UserControl1View />
</DataTemplate>

// and the same for UserControl2ViewModel

有些UserControl中的控件绑定到SharedUserControlData.MyCollection和其他UserControlViewModels属性。MainWindow的DataContext是MainWindowViewModel:

IRepository repository = new MyRepository(); // or use Dependency Injection
MainWindow window = new MainWindow();
MainWindowViewModel viewModel = new MainWindowViewModel(repository);
window.DataContext = viewModel;

在您的MainWindow的XAML中,我们将UserControls绑定到MainWindow的DataContext(即MainWindowViewModel)的嵌套ViewModels。
<StackPanel>
    <v:UserControl1View DataContext="{Binding UserControl1ViewModel}" />
    <v:UserControl2View DataContext="{Binding UserControl2ViewModel}" />
</StackPanel>

这样,两个UserControls将拥有不同的ViewModels,但它们都共享来自包含两个UserControl's ViewModels的更高级别的ViewModel中的相同的SharedData实例。然后,Repository就可以访问EF数据上下文。(在这里拥有存储库只是一个示例,您还可以注入Service类的实例或其他内容。)


非常感谢您提供的全面示例!非常感激。我会研究一下这个。 - TripleAntigen

1

我完全赞同每个视图使用一个ViewModel的方法。对于共享数据,你可以传递引用(繁琐且容易出错),你可以使用依赖注入(取决于你的舒适度,但不太适合设计时数据),或者你可以在App.xaml.cs中创建静态属性,然后在整个应用程序中共享和访问。从长远来看,依赖注入可能会得到其他人的最大支持。


0
你可以查看WPF应用程序框架(WAF)BookLibrary示例应用程序。它包含两个不同的视图(BookListView [主视图],BookView [详细视图]),用于相同的数据源,该数据源由Entity Framework提供。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接