Loading Fluent Menu at run-time

I started playing around with WPF a little bit. Of course I also wanted to build a proper ribbon interface if I was creating a windowed application. Microsoft’s Ribbon Package was ok, but I was looking for more. If you want a good list, check out the discussion here. Ultimately I decided for the open source solution on codeplex. Of course I wasn’t happy just to have a ribbon, it had to use Prism as well. I don’t do things half-baked. Prism – for those who don’t know – is a library from Microsoft which helps to implement the MVVM Paradigm. (as described in a MSDN Article)

As part of the model I needed to load a menu when a view is loaded in a region. You have two options:

  • Show/Hide a menu on demand – eh, not really. The view was defined in a separate module and I didn’t want to define the module in the Shell in advance
  • Load the menu at run-time from the module – much better. Of course I didn’t want to program the menu but insert a control.

So, making my life as difficult as possible, I defined following fragment

<Fluent:RibbonGroupBox xmlns:Fluent=”clr-namespace:Fluent;assembly=Fluent” 
                       xmlns:Common=”clr-namespace:EnnfDesigner.Common.ShellServices;assembly=EnnfDesigner.Common”
                      Name=”TrainingMenu” Header=”Training” Common:NavigationOrder.Order=”1″>
    <Fluent:Button Header=”Test data” />
    <Fluent:Button Header=”Target data” />
</Fluent:RibbonGroupBox>

Code 1: Fluent RibbonGroupBox Fragment

Note the property Common:NavigationOrder.Order=”1”; this is an Attached Property added to allow the loading component determine where in the menu structure the item should be placed.

This wasn’t too difficult, the real trick is to figure out how to load the fragment and then insert this at run time. The solution is

private static RibbonGroupBox FindRibbonGroupBox(Assembly callingAssembly, string menuName)
        {
            Uri uri = new Uri(String.Format(“pack://application:,,,/{0};component{1}”, callingAssembly.GetName().Name, menuName), UriKind.RelativeOrAbsolute);
            StreamResourceInfo streamResource = Application.GetResourceStream(uri);
            if (streamResource == null)
                throw new ArgumentException(Resources.MenuResourceNotFound, “menuName”);
            Baml2006Reader bamlReader = new Baml2006Reader(streamResource.Stream);

            return XamlReader.Load(bamlReader) as RibbonGroupBox;
        }

Code 2: Loading RibbonGroupBox at run-time

Look at the callingAssembly. This I use to determine a part of the Package URI which locates the WPF Control.  The other part of the Package URI is the menuName parameter. The complete URI would look something like this

pack://application:,,,/Module;component/SubDir/fragment.xaml

This is used to locate the resource in the component to then read the Baml – a kind of Binary Xaml – via the Baml2006Reader. Finally use the XamlReader.Load Method to create the RibbonGroupBox.

Finally, adding the RibbonGroupBox is just a matter of Adding or Inserting it into the correct collection.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: