Prism 2 & Silverlight 3 Beta Navigation

Topics: Prism v2 - Silverlight 2
Mar 24, 2009 at 12:23 AM
Hi all,

I'm having an issue that I could do with some help with.

I'm running an application with 2 modules (ModuleA & ModuleB). Before Silverlight 3 Beta was released I was using a simple custom navigation model in which I would navigate directly to an object rather than to a URI. Now I'm trying to migrate to using the proper navigation framework provided.

I've setup my UriMappings in App.xaml to point to a view within a module (a .xap package) like so:

<navcore:UriMapping Uri="MyViewA" MappedUri="/ModuleA;component/Views/MyView.xaml"/>
<navcore:UriMapping Uri="MyViewB" MappedUri="/ModuleB;component/Views/MyView.xaml"/>

Now when I browse to MyViewA or MyViewB the navigation system successfully finds the right .xaml file but is then unable to find the class which the XAML file references (x:Class="..."). I've tracked down the cause of this issue to the fact that the navigation framework loops through all the available AssemblyPart instances (Deployment.Current.Parts) and tries to find a matching assembly within the list. These are, of course, the list of assemblies defined in in the AppManifest.xaml file.

With Prism 2, both of my modules are loaded dynamically and so don't have any reference in AppManifest.xaml and so there will never be a match. However, the type that is required is still loaded by the Silverlight client it just isn't in the Parts collection. Type.GetType("ModuleA.MyView") would still work, but never gets called.

So, what I'm looking for is a way to dynamically add a dynamically loaded assembly from a package into the Deployment.Current.Parts collection and to be recognised.

I've tried adding several assembly parts, but none of them will be resolved in a call to Application.GetResourceStream(Uri):

- new AssemblyPart { Source = "/ModuleA" }
- new AssemblyPart { Source = "/ModuleA.xap" }
- new AssemblyPart { Source = "/ModuleA;component/ModuleA.dll" }
- new AssemblyPart { Source = "/ModuleA.xap;component/ModuleA.dll" }

Is anybody aware of a URI that I could use that would resolve from a call to Application.GetResourceStream(Uri) (which System.Windows.Navigation does, not me, so I can't use the overload which allows a package stream to be passed in).

Thanks in advance,
Scriv
Mar 25, 2009 at 7:55 PM

Hi Scriv,

 

I have been able to reproduce your issue but could not find a fix/workaround for it. My approach updating the code of the LoadAssemblyFromStream method of the XapModuleTypeLoader class provided by the CAL (this is not the best approach, but if it had worked you could have created a custom module type loader):

    private static void LoadAssemblyFromStream(Stream sourceStream, AssemblyPart assemblyPart)

        {

            Stream assemblyStream = Application.GetResourceStream(

                new StreamResourceInfo(sourceStream, null),

                new Uri(assemblyPart.Source, UriKind.Relative)).Stream;

 

            assemblyPart.Load(assemblyStream);

            Deployment.Current.Parts.Add(assemblyPart); //This is the new line.

        }

 

This behavior however, only takes place when loading modules remotely (I have tried loading modules statically and been able to perform navigation successfully).

 

Bear in mind that Prism-v2 was not focused on providing navigation support, not even for WPF. If you feel that a future version of Prism (which will target Siliverlight 3.0 & WPF 4.0 as David Hill says in this post) should have this feature, or another one included, you could create an item in the IssueTracker, so people can vote for it. The team might take it into account for future versions.

 

Please let me know if this helps.

 

Damian Schenkelman

http://blogs.southworks.net/dschenkelman