Внедрить представления в ItemsControl в зависимости от типа объекта - PullRequest
3 голосов
/ 17 апреля 2011

У меня есть служба, возвращающая массив типа Party.Партия имеет два подтипа, Персона и Организация.Я использую этот сервис в своем приложении WPF (Prism, MVVM) из модели представления.В конструкторе этой модели представления я заполняю наблюдаемую коллекцию типа Party:

public PhoneBookViewModel(IPhoneBookService phoneBookProxy)
{
    _phoneBookProxy = phoneBookProxy;

    var parties = _phoneBookProxy.GetAllParties();
    _parties = new ObservableCollection<Party>(parties.ToList());
}

Пока все хорошо.В моем PhoneBookView у меня есть ItemsControl, который привязывается к этой коллекции.В этом элементе управления я хочу визуализировать каждую сторону, используя другой вид (и модель его вида).Поэтому, когда Party имеет тип Person, вставьте PersonView и передайте объект Party в конструктор PersonViewModel, а когда Party имеет тип Organisation, визуализируйте OrganizationView и т. Д. ... Вы получите изображение (или?).

Но я не могу понять, как это сделать в XAML.Есть идеи?Это, вероятно, не лучший способ сделать это, поэтому, если вы можете порекомендовать лучший подход, пожалуйста, просветите меня: -)

Спасибо!

Ответы [ 4 ]

1 голос
/ 17 апреля 2011

Давайте рассмотрим это с точки зрения модели:

<Ч />

Предположим, у нас есть 2 различных типа представлений, 1 тип модели представлений:

ViewA -> Создано в элементе управления с использованием DataTempate / DataTemplateSelector, Binded> to ViewModelA

ViewB -> Создано в элементе управления, используя DataTempate / DataTemplateSelector, привязанный к ViewModelA

Если оба вида привязаны к одной и той же модели вида, вы получите один и тот же вид.

<Ч />

Давайте попробуем еще раз с 2 различными типами представлений и 2 различными типами моделей представлений:

ViewA -> Создано в элементе управления с использованием DataTempate / DataTemplateSelector, привязано к ViewModelA -> Привязано к ModelA

ViewB -> Создано в элементе управления с использованием DataTempate / DataTemplateSelector, привязано к ViewModelB -> Привязано к ModelB

Это возможно.

<Ч />

Теперь, если вы моделируете свои модели вида и модели, подобные этой (псевдокод):

public PhoneBookViewModel
{
    public PhoneBookViewModel()
    {
        _parties = new ObservalbeCollection<PartyViewModel>();
    }

    private PhoneBook _dataContext;

    // This is the property the VM uses to access the model
    public PhoneBook DataContext
    {
        get { return _dataContext; }
        set
        {
            if (_dataContext != null)
            {
                _dataContext.Parties.CollectionChanged -= OnModelPartiesChanged;
            }
            _dataContext = value;
            if (_dataContext != null)
            {
                _dataContext.Parties.CollectionChanged += OnModelPartiesChanged;
            }
        }
    }

    private ObservableCollection<PartyViewModel> _parties;

    // This is the property the view uses to access the collection of VM parties
    public ObservableCollection<PartyViewModel> PartiesViewModels { get { return _parties; } }

    private void OnModelPartiesChanged(...)
    {
        // Add/remove VMs to/from PartiesViewModels here
    }
}

// Model
public PhoneBook
{
    public PhoneBook()
    {
        _parties = new ObservalbeCollection<Party>();
    }

    private ObservableCollection<Party> _parties;

    // This is the property the VM uses to access the model's parties
    public ObservableCollection<Party> Parties { get { return _parties; } }
}

public PersonViewModel : PartyViewModel
{
    new Person DataContext { get; set; }
}

public PartyViewModel
{
    public Party DataContext { get; set; }
}

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

<Ч />

Таблицы данных вида:

<DataTemplate x:Target={x:Type myVmNamespace:PersonViewModel}">
    <PersonView/>
</DataTemplate>

<DataTemplate x:Target={x:Type myVmNamespace:GroupViewModel}">
    <GroupView/>
</DataTemplate>

Просмотр элементов управления:

<!-- Bind to Parties property of PhoneBookVM -->
<!-- Uses datatemplates for items -->
<ListView ItemsSource={Binding Parties}"/>
0 голосов
/ 18 апреля 2011

Ваша коллекция для вашего ItemsControl ItemsSource заполнена PhoneBookViewModel. Поэтому остается только сказать WPF, как должен отображаться каждый элемент этой коллекции. И этого легко достичь, создав DataTemplate.

 <DataTemplate DataType="{x:Type PersonViewModel}"> 
     <MyPersonView/> 
 </DataTemplate>
0 голосов
/ 17 апреля 2011

Если вы используете Prism и MVVM, то вы привязываете Команду к вашему ItemsControl со всеми сторонами.

Эта команда будет иметь тип DelegateCommand<Party>.Внутри делегата выполняется команда, которая будет выглядеть следующим образом:

private void PartyNavigate(Party party)

Просто проверьте, является ли участник каким-либо из подтипов, и вызовите RequestNavigate в области вашего RegionManager дляКонкретное представление.

В этом случае возникнет проблема с передачей фактического контекста. Вы также можете посмотреть на MVVM RI, поставляемый с Prism, который имеет очень хороший подход к этому в виде * 1011.* или вы можете создать свой собственный централизованный DataManager, в котором вы будете следить за состоянием этих вещей, а также за кэшированием, которое вы получаете от WebServices, и т. д. После 2 лет создания интеллектуальных клиентов с WPF и WCF я могу вам сказать, что в конечном итоге вам потребуетсясоздайте свой собственный DataManager, который не составит большого труда, если вы уже используете EntityFramework и большую часть его генерируете из EDM.

0 голосов
/ 17 апреля 2011

Настройте шаблон данных для ваших типов данных для визуализации xaml.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...