Как повторно использовать источник данных каркаса сущностей для нескольких представлений WPF EF MVVM - PullRequest
3 голосов
/ 19 марта 2011

Привет, я разрабатываю приложение с использованием WPF4, EF и MVVM.Я хочу иметь возможность создавать повторно используемые пользовательские элементы управления, которые я могу использовать в нескольких окнах приложения, и получать от них данные из одного источника.

Допустим, у меня есть компонент GraphView и компонент TableView, которые могут появляться на одной странице или в разных местах приложения, и я хочу, чтобы они оба отражали одну и ту же коллекцию отфильтрованных объектов EF.Обычная практика MVVM, кажется, требует, чтобы у каждого представления была своя собственная модель представления.Но должен ли я использовать совместную модель представления и связать обе с ней, так что если вы измените данные или фильтр, оба будут обновлены одновременно?Если нет, то как мне справиться с этим?

Спасибо за любой совет!

Ответы [ 4 ]

2 голосов
/ 19 марта 2011

Одним из подходов может быть наличие двух ViewModel, по одному для каждого из ваших Views / UserControls, а затем вложение их в какую-либо 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 из UserControls вводят эти данные:

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

    public SharedUserControlData SharedUserControlData { get; private set; }

    // more stuff
}

// and the same for UserControl2ViewModel

Ваши представления UserControl привязаны к моделям представления с помощью шаблона данных:

<DataTemplate DataType="{x:Type vm:UserControl1ViewModel}" >
    <v:UserControl1View />
</DataTemplate>

// and the same for UserControl2ViewModel

А некоторые элементы управления внутри UserControls связаны затем с SharedUserControlData.MyCollection и другими свойствами UserControlViewModels. DataContext MainWindow - это MainWindowViewModel:

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

В XAML вашего MainWindow мы связываем UserControls с вложенными ViewModels DataContext MainWindow (который является MainWindowViewModel):

<StackPanel>
    <v:UserControl1View DataContext="{Binding UserControl1ViewModel}" />
    <v:UserControl2View DataContext="{Binding UserControl2ViewModel}" />
</StackPanel>

Таким образом, оба UserControls будут иметь разные ViewModel, но оба будут использовать один и тот же экземпляр SharedData, который поступает из ViewModel более высокого уровня, содержащего оба ViewModels UserControl. Затем репозиторий получает доступ к контексту данных EF. (Наличие репозиториев здесь - только пример, вы также можете добавить экземпляры классов Service или что-то в этом роде.)

2 голосов
/ 19 марта 2011

Ваши классы EF, насколько я могу судить после всего лишь четырех дней использования EF, находятся на уровне проекта. Моим первым инстинктом было бы реализовать синглтон, содержащий ссылки на сущности, которые вы хотите сохранить общими для ваших моделей представления. Это, конечно, создаст зависимость класса от вашего синглтона.

На самом деле это звучит как проблема проектирования, решаемая Unity, MEF или чем-то еще, что приведет к внедрению зависимости. Ваши классы EF будут храниться в модуле одной из этих платформ и использовать их протоколы для координации между EF и виртуальными машинами. Затем изменение в вашем фильтре или ваших данных в EF также приведет к появлению сообщения, которое ваша виртуальная машина может зарегистрировать для получения, чтобы инициировать изменения пользовательского интерфейса или изменения состояния виртуальной машины или что-то еще.

1 голос
/ 19 марта 2011

Я полностью согласен с подходом ViewModel для View.Для общих данных вы можете либо передавать ссылки (утомительно и подвержено ошибкам), вы можете использовать DI (в зависимости от вашего уровня комфорта, но не очень хорошо с данными времени разработки), либо вы можете создавать статические свойства в вашем App.xaml.CS, которые затем передаются и доступны по всему приложению.В долгосрочной перспективе DI, вероятно, получит наибольшую поддержку от других людей.

0 голосов
/ 05 мая 2011

Вы можете взглянуть на BookLibrary пример приложения WPF Application Framework (WAF) . Он содержит два разных представления (BookListView [Master], BookView [Detail]) для одного и того же источника данных, который предоставляется Entity Framework.

...