Использование MEF для импорта шаблона данных WPF? - PullRequest
24 голосов
/ 09 мая 2009

Я смотрел на MEF как на платформу расширяемости, и я в значительной степени продан, за исключением одного пункта:

Допустим, я хочу импортировать и ViewModel, и View для его отображения. Я думаю, что «правильный» способ сделать это для части MEF - экспортировать класс ViewModel и DataTemplate, который отображает ViewModel. Например, предположим, что вы создавали приложение, похожее на Visio, и хотите импортировать библиотеку фигур. Каждой фигуре требуется представление, определенное в Xaml, и ViewModel, который обернул бы некоторый базовый объект Model.

Возможно ли это? Как будет выглядеть контракт на импорт для DataTemplate и как мне сделать так, чтобы WPF знал об импортированном DataTemplate?

1 Ответ

39 голосов
/ 10 мая 2009

Да, я смог сделать эту работу следующим образом:

В своем приложении WPF хоста я добавил этот импорт:

    [ImportMany("ApplicationResources", typeof(ResourceDictionary))]
    public IEnumerable<ResourceDictionary> Views { get; set; }

Затем в своей составной части я объявил ViewModel и шаблон данных для ViewModel в обычном Xaml-файле ResourceDictionary. Затем я создал код для ResourceDictionary, например так (в этом примере ViewModel называется ItemViewModel, а ResourceDictionary называется ItemView):

[Export("ApplicationResources", typeof(ResourceDictionary))]
public partial class ItemView : ResourceDictionary 
{
    public ItemView()
    {
        InitializeComponent();
    }
}

Для справки, Xaml для примера ResourceDictionary выглядит так:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyCompany.MyProduct"
    x:Class="MyCompany.MyProduct.ItemView">

    <DataTemplate DataType="{x:Type local:ItemViewModel}">
        ...
    </DataTemplate>

</ResourceDictionary>

Затем, вернувшись в мое приложение WPF хоста, после того, как я успешно скомпоновал и перед тем, как показать главное окно, я делаю это:

// Add the imported resource dictionaries
// to the application resources
foreach (ResourceDictionary r in Views)
{
    this.Resources.MergedDictionaries.Add(r);
}

Похоже, что успешно применяется DataTemplate везде, где WPF видит ItemViewModel.

РЕДАКТИРОВАТЬ : Для тех, кто заинтересован, я выпустил платформу приложения под названием SoapBox Core в качестве открытого источника, и он широко использует этот метод для импорта представлений в ресурсы приложения. Он работает очень хорошо, и вы можете сами загрузить исходный код и посмотреть, как он работает.

...