WPF MVVM: соглашение о конфигурации для ResourceDictionary? - PullRequest
6 голосов
/ 20 апреля 2009

Обновление

В духе вики StackOverflow, вот обновление:

Я добавил предложение IValueConverter Джо Уайта ниже. Отлично работает.

Я написал «быстрый старт» этого примера, который автоматизирует отображение ViewModels-> Views с использованием некоторой дешевой замены строки. Если не найден View, представляющий ViewModel, по умолчанию используется страница «В разработке». Я называю этот подход "WPF MVVM White", так как это была идея Джо Уайта. Вот пара скриншотов.

Первое изображение - это случай, когда «[SomeControlName] ViewModel» имеет соответствующий «[SomeControlName] View», основанный на соглашении о чистых именах . Второй случай, когда ModelView не имеет никаких представлений для его представления. Нет больше ResourceDictionaries с длинными ViewModel для отображения отображений. Теперь это соглашение по именованию.

Wpf Mvvm White

Я разместил загрузку проекта здесь: Mvvm.White.Quickstart.zip


Исходное сообщение

В выходные я прочитал фантастическую статью MSDN Джоша Смита о WPF MVVM. Это суждено стать культовой классикой.

Мне потребовалось некоторое время, чтобы обернуться вокруг магии - попросить WPF визуализировать ViewModel .

Это все равно, что сказать: «Вот класс, WPF. Пойди выясни, какой интерфейс использовать для его представления».

Для тех, кто пропустил это волшебство, WPF может сделать это, просмотрев View для ModelView в сопоставлении ResourceDictionary и вытянув соответствующий View . (Прокрутите вниз до . Рисунок 10. Предоставление представления ).

Первое, что сразу бросается в глаза, это то, что уже существует строгое соглашение об именах:

classNameView  ("View" suffix)
classNameViewModel ("ViewModel" suffix)

Мой вопрос:

Поскольку ResourceDictionary можно манипулировать программно, мне интересно, удалось ли кому-нибудь выполнить регулярное выражение Regex. Замените все это, , чтобы поиск выполнялся автоматически , и любой новый вид / ViewModels разрешаются в соответствии с соглашением об именах?

[Редактировать] Я представляю себе ловушку / перехват в ResourceDictionary.

... Также рассматривается метод при запуске, который использует взаимодействие для извлечения имен классов *View$ и *ViewModel$ для построения словаря DataTemplate в коде:

//build list
foreach ....
    String.Format("<DataTemplate DataType=\"{x:Type vm:{0} }\"><v:{1} /></DataTemplate>", ...)

Ответы [ 2 ]

17 голосов
/ 25 апреля 2009

Вместо того, чтобы писать код для явного добавления объектов в ResourceDictionary, как насчет создания правильного представления по требованию? Вы можете сделать это с помощью ValueConverter.

Ваши ресурсы будут выглядеть так:

<Views:ConventionOverConfigurationConverter x:Key="MyConverter"/>
<DataTemplate DataType="{x:Type ViewModels:ViewModelBase}">
    <ContentControl Content="{Binding Converter={StaticResource MyConverter}}"/>
</DataTemplate>

Вам по-прежнему нужен ресурс DataTemplate, но пока все ваши ViewModels имеют общий базовый класс, вам потребуется только один DataTemplate, чтобы позаботиться обо всех них.

Затем определите класс преобразователя значений:

public class ConventionOverConfigurationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        // value is the ViewModel. Based on its GetType(), build a string
        // with the namespace-qualified name of the view class, then:
        return Activator.CreateInstance(Type.GetType(viewName));
    }
    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

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

0 голосов
/ 01 мая 2009

Я решил сделать то же самое, поэтому я загружаю свои DataTemplates прямо в ResourceDictionary с помощью

    private void RegisterResources()
    {
        ResourceDictionary dictionary = new ResourceDictionary();
        dictionary.Source = new Uri("pack://application:,,,/StartupModule;Component/UIResources.xaml");
        Application.Current.Resources.MergedDictionaries.Add(dictionary);
    }

где файл UIResources является файлом xamls ResourceDictionary, содержащим все наши шаблоны данных

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