Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
631 views
in Technique[技术] by (71.8m points)

mvvm - Using MEF to import a WPF DataTemplate?

I was looking at MEF as an extensibility framework, and I'm pretty much sold, except for one point:

Let's say I want to import both a ViewModel and a View to display it. I think the "right" way to do that is for the MEF part to export a ViewModel class, and a DataTemplate that displays the ViewModel. As an example, say you were building a Visio-like application and you want to import a library of shapes. Each shape needs a View defined in Xaml and a ViewModel that would wrap some underlying Model object.

Is this possible? What would the Import contract look like for the DataTemplate and how do I make WPF aware of the imported DataTemplate?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, I was able to make this work in the following way:

In my host WPF application, I added this Import:

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

Then in my composite part, I declared a ViewModel, and a data template for the ViewModel in a regular ResourceDictionary Xaml file. Then I created a code behind for the ResourceDictionary, like this (in this example, the ViewModel is called ItemViewModel and the ResourceDictionary is called ItemView):

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

For reference, the Xaml for the example ResourceDictionary looks like this:

<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>

Then, back in my host WPF application, after I successfully compose and before I show the main window, I do this:

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

That seems to successfully apply the DataTemplate anywhere WPF sees an ItemViewModel.

EDIT: For anyone who's interested, I released an application framework called SoapBox Core as open source, and it uses this method extensively to import Views into the application resources. It works very well, and you can download the source yourself and take a look at how it works.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...