On demand shared or non-shared instantiation

Sep 1, 2010 at 2:15 AM

I have multiple WPF Views and they all use the same .NET type as their ViewModel.

Typically, when I create a new View I get a new instance of ViewModel because creation policy was explicitly specified as not shared.

However, in some cases I want for a new View to reuse ViewModel from another, already existing View.

Say, for example, that existing View is about to be closed and the new View, about to be created, should carry on with the current state of its ViewModel instance.

Sure, if I am doing everything manually I am in complete control so I create what I want when I want.

But for several extensibility-related reasons I have MEF create ViewModel (and Model) parts, so I am looking for suggestions on what would be the way to handle this scenario via MEF? 

Currently I am using MeffedMVVM to create ViewModels for each View.

Thanks!

Sep 1, 2010 at 11:32 AM
Edited Sep 1, 2010 at 11:36 AM

I'll disclose up front that I'm pretty new to MEF...

I'm wondering if you could decorate your view's constructor with [ImportingConstructor], and accept your ViewModel as one of the constructor's parameters.  That way, you could instantiate your View in the cases where you want to manually inject your ViewModel, and you could let MEF instantiate your View in cases where you want a new one created by MEF.

Code where you instantiate might look like this:

 

MyView myView = null;
if (IWantToInstantiateAndInjectExistingViewModel)
{
myView = new MyView(existingMyViewModel);
container.ComposeParts(myView);
}
else // I want mef to instantiate my view and create a view model
{

 

    Type type = typeof(MyView);

 

    IEnumerable<Export> matching = container.GetExports(
new ContractBasedImportDefinition(
AttributedModelServices.GetContractName(type),
AttributedModelServices.GetTypeIdentity(type),
null,
ImportCardinality.ZeroOrMore,
false,
false,
CreationPolicy.Any));

myView = matching.Single().Value;
}

 

...

 

public class MyView
{
    private MyViewModel myViewModel { get; set; }

    [Import]
    public SomeOtherMEFImport someOtherMEFImport { get; set; }

    [ImportingContstructor]
    public MyView(MyViewModel myVM)
    {
        myViewModel = myVM;
    }
}

 

Sep 2, 2010 at 12:43 AM

Right, thanks for contributing Michael! I was thinking along the similar lines. Since I am using this library :

http://mefedmvvm.codeplex.com/

I will ask the library author about the right place to intercept default library VM creation (via MEF) and use existing VM object instead. 

BTW, the thread that you started: How to get MEF to instantiate and compose my Type:

http://mef.codeplex.com/Thread/View.aspx?ThreadId=225124

is interesting for my scenario too. Glenn's response seems to imply that there is a simpler way to "dynamically retrieve from the container based on a runtime type".

I guess he will eventually explain what he meant by that in more details.