WPF DataTemplate / DataTemplateSelector - лучший подход для модели представления, используемой двумя различными представлениями? - PullRequest
1 голос
/ 14 апреля 2011

В основном, у меня есть следующий сценарий:

ViewModel: FooViewModel : BaseViewModel, BarViewModel : BaseViewModel
Просмотров: MainView, FooView, BarView

Прямо сейчас я «внедряю» вид и устанавливаю DataContext, используя DataTemplate и DataTemplateSelector. Очевидно, что мой ItemsControl ItemSource связан с ObservableCollection<BaseViewModel>, в котором он содержит (на данный момент) экземпляр FooViewModel и BarViewModel

Проблема в том, что я хочу ввести AlternateFooView, который я хочу использовать тот же FooViewModel. Я полагаю, что создам еще один DataTemplate, и мой DataTemplateSelector вернет его, но должна быть специальная логика, чтобы определить, какой DataTemplate нужно вернуть (я не могу просто определить, какая ViewModel там есть), и это означает, что я Вам нужно будет иметь некоторый тип свойства или поля в BaseViewModel. Я не знаю, действительно ли это хорошая идея, потому что кажется, что в ViewModel вводится поле / свойство, которое используется только для выбора вида. Это не повредит моему модульному тестированию, но кажется пустым, чтобы включить поле только для того, чтобы решить, какой вид интерфейса выбрать. Я не думаю, что это ломает MVVM, но мне любопытно, есть ли у кого-нибудь еще идеи получше? Альтернативные идеи, которые у меня были, мне даже больше не нравятся ...

Идея № 2:
- Превратите FooViewModel в базовый класс, который расширяют 2 разных FooViewModel (то есть BaseFooViewModel, FooViewModel, DifferentFooViewModel). Это кажется глупым, потому что на самом деле нет никакой разницы между FooViewModel и DifferentFooViewModel, кроме их типа класса.

Идея № 3:
- Просто скопируйте FooViewModel и сделайте его FooViewModel2 (он будет полностью идентичен FooViewModel). Это кажется даже хуже, чем идея № 2.


Код образца (корректируется явно):
public abstract class BaseViewModel : NotificationObject
{
    //Common Stuff
}

public abstract MainViewModel : NotificationObject
{
    public MainViewModel()
    {
        MyItems = new ObservableCollection<BaseViewModel>()
        {
            new FooViewModel();
            new BarViewModel();
            new FooViewModel(); //New Item -- I want it to use the DifferentFooView
        }
        //Load items from a DAL later
    }

    public ObservableCollection<BaseViewModel> MyItems { get; set; }

    //Other Stuff
}

<l:MyItemsControl ItemSource={Binding MyItems} ContentTemplateSelector={StaticResource MyTemplateSelector} />


Спасибо!

1 Ответ

4 голосов
/ 14 апреля 2011

Я согласен с Кришнаадитьей, что вопрос действительно сводится к тому, что определяет, какой View использовать, основываясь на состоянии ViewModel.Этот тип логики часто помещается в селектор шаблонов, который прекрасно работает.Если вы не хотите помещать эту логику в селектор шаблонов, рассмотрите возможность ее использования с помощью моего подхода Routed Template Selection .Это позволяет легко делегировать логику выбора шаблона с помощью перенаправленного события.

Идея, которую вы предложили в своем комментарии об использовании DataTrigger, также может работать, но при этом вновь возникает потребность в свойстве объекта VM, котороеуказывает, какой вид загрузить (который вы сказали, что не хотите)На мой взгляд, это не обязательно плохо.

...