Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PRISM 4 - RegisterViewWithRegion & Custom Export Attributes

Tags:

mef

prism

regions

I am using Prism 4 with MEF Extensions and the MVVM pattern. During initialization in a module I call RegisterViewWithRegion(RegionNames.MyRegion, typeof(MyView)) which works perfectly when the view is constructed like this:

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class MyView : UserControl
{
    public MyView()
    {
     ....

The view gets registered and everything is fine. As soon as I change the Export to a Custom Export Attribute the view can't be found anymore, although it is still in the container. This Custom Export Attribute is taken from the Stock Trader RI:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
[MetadataAttribute]
public class ViewExportAttribute : ExportAttribute, IViewRegionRegistration
{
    public ViewExportAttribute()
        : base(typeof(object))
    { }

    public ViewExportAttribute(string viewName)
        : base(viewName, typeof(object))
    {
        ViewName = viewName;
    }

    public string RegionName { get; set; }
    public string ViewName { get; set; }

}

and the interface is

public interface IViewRegionRegistration
{
    string RegionName { get; }
    string ViewName { get; }
}

By changing the Export Attribute to

[ViewExport(ViewName = "MyView", RegionName = RegionNames.MyRegion)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class MyView : UserControl
{
    public MyView()
    {
    ....

when calling RegisterViewWithRegion it throws an error: Activation error occured while trying to get instance of type MyView, key ""

Any advice? I was looking at this part of code the whole day without finding a solution.

like image 320
okieh Avatar asked Jun 07 '11 20:06

okieh


2 Answers

Another day, another way... I will try to answer my question even though I have only limited knowledge about PRISM. In other words: I'm still learning.

The Custom Export Attribute taken from the Stock Trade RI is used by the AutoPopulateExportedViewsBehavior. This behavior adds a view to its region automatically by checking the Export Attribute for the region name then adds the view to the corresponding region. But all views with this Custom Attribute now have a contract name of "object" which makes it impossible for the ServiveLocator to find them. This Custom Attribute is for a scenario with fixed region/view links. A solution when working with a Custom Export Attribute is to get all exports of type "object" and the appropriate metadata:

MyView view;
var myList = container.GetExports<object, IViewRegionRegistration>();
foreach (Lazy<object, IViewRegionRegistration> lazy in myList)
{
    if (lazy.Metadata.ViewName == "MyView")
    {
        view = lazy.Value as MyView;
        region.Add(view);
        break;
    }
}

But I think when using ViewInjection and Prism Navigation it is better to just use the default [Export] attribute, then everything works smoothly.

like image 128
okieh Avatar answered Sep 19 '22 12:09

okieh


Are you configuring the aggregate catalog in your MEF bootstrapper? If so, are you adding the assembly that contains your ViewExportAttribute and AutoPopulateExportedViewsBehavior classes? I believe this happens in the StockTraderRI's bootstrapper with this line:

this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(StockTraderRICommands).Assembly));

The StockTraderRICommands class is in the same assembly as the ViewExportAttribute and AutoPopulateExportedViewsBehavior classes.

like image 42
Nicolaus Avatar answered Sep 19 '22 12:09

Nicolaus