MEF Navigation Library for WPF

Feb 9, 2012 at 2:54 PM

Hello,

I'm developing a MEF navigation Library to be used on WPF. I already did the same for SL4/5 and works like a charm but in WPF I'm havinf a strange error.

The Navigation Service has a Lazy Property that it's been populate very well with all the Views that I want to export

<ImportMany("ModalWindow", AllowRecomposition:=True, RequiredCreationPolicy:=CreationPolicy.NonShared)>
Protected Property ModalWindowsLazy As IEnumerable(Of Lazy(Of Object, IModalWindowMetadata
))

In the NavigationService constructor I have the composeParts(Me) and this property as the values that I want. When I want to navigate to a ModalWindow I have this:

Public Sub NavigateToModal(modalWindowName As String)

 Dim oAUX As Window = ModalWindowsLazy.[Single](Function

(x) x.Metadata.Name.Equals(modalWindowName)).Value 
 
oAUX.ShowDialog()   

 

 

End Sub

When I try to open this windows again I get an error

Can not set Visibility or call Show, ShowDialog WindowInteropHelper.EnsureHandle or after closing a Window object.

I look in the web and look like I have to Release the export... but I can't find a way to do that...can anyone explain that to me?



regards

Paulo Aboim Pinto

 

 

 

 

Feb 9, 2012 at 11:29 PM

Hi Paulo,

It would seem that a window can only be used once in this manner, i.e. after you've called .ShowDialog() once and the user has closed the dialog, you can't again call ShowDialog() on the same window object.

Specifying CreationPolicy.NonShared on the import will mean that the imported collection will contain unique instances of each modal window, however the collection is fixed - each time you call Lazy.Value for the same element, you'll get the same window object back.

In MEF 2, i.e. .NET 4.5 Developer Preview or the version of MEF on CodePlex, you can use the ExportFactory type instead of Lazy to handle exactly this issue.

http://blogs.msdn.com/b/bclteam/archive/2011/11/17/exportfactory-amp-lt-t-amp-gt-in-mef-2-alok.aspx

If you are targeting .NET 4.0, you most likely have to call GetExport() on CompositionContainer, or else import ICompositionService and use SatisfyImports() on a helper object each time a new window is required.

Let us know which version you're targeting and we can provide more details.

Regards,
Nick

Feb 10, 2012 at 7:56 AM

Hello and thanks for the answer.

I put the code in the call for each window and now it's working.

_container.SatisfyImportsOnce(Me)

One question. With lot's of imports, this code will not be slow? Right now I have just one Export and was very fast. Imagine that I have 100 in several assemblies? How it's gonna work?

I try to use the GetExports() but what will be the parameters? I already try:

Dim test = _container.GetExports(Of Object, IModalWindowMetadata)()

Dim test = _container.GetExports(Of Object, IModalWindowMetadata)(modalWindowName)

Dim test = _container.GetExports(Of Object)(modalWindowName) 

 

in all cases the test variable has nothing, Count = 0. My Lazy definition it's:

<ImportMany("ModalWindow", AllowRecomposition:=True, RequiredCreationPolicy:=CreationPolicy.NonShared)>
Protected Property ModalWindowsLazy As IEnumerable(Of Lazy(Of Object, IModalWindowMetadata))

 

what should be the parameters in the GetExport to get the right export and just reload that export?

 

tkx one more time
Paulo Aboim Pinto

 

Feb 10, 2012 at 4:41 PM

Hi,

I think you're on the right track. To make this work you need to change the way the windows are exported. Instead of using metadata, try setting a unique contract name (and the contract type Window) for each exported window:

  <Export("FooWindow", GetType(Window))>

Then, use the contract name to retrieve the single corresponding export:

  Dim test = _container.GetExport(Of Window)("FooWindow")

This will perform adequately when large numbers of windows are involved.

Don't forget to call ReleaseExport() when you're finished with the dialog.

Hope this helps!

Nick