Thursday, November 27, 2008

XAML factoring


We are using the Infragistics Ribbon component in our application.  Our application has the same Ribbon Group content specified in multiple tabs.  I was looking for a way to share the group content so it wasn't copied and pasted in both locations.

I searched online and found a forum where one of their staff said it was not a feature.

This is not a problem as WPF allows you to share UI elements for compiled resource dictionaries.

When we compile XAML we get BAML stored inside the assembly as a resource.  This allows the x:Shared keyword to enable special functionality not available from C#.   Why not IL?  BAML is more compact than IL, can be localized after compilation, and is less of a security threat.

Specifying x:Shared in a resource dictionary means the content will be fetched new each time it is requested allowing the same user interface elements to be added in multiple places.

Here is an example:
    <Window.Resources>
        <StackPanel x:Key="moreContent" x:Shared="false">
            <TextBlock Text="local" />
        </StackPanel>
    </Window.Resources>
    <StackPanel>
        <StaticResourceExtension ResourceKey="moreContent" />
        <StaticResourceExtension ResourceKey="moreContent" />
    </StackPanel>
One may also put the shared content in another XAML file to share the resource with other XAML files in your application:
Window1.xaml

    <Window.Resources>
        <ResourceDictionary >
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Ribbon.xaml" />
            </ResourceDictionary.MergedDictionaries>
            <StackPanel x:Key="moreContent" x:Shared="false">
                <TextBlock Text="local" />
            </StackPanel>
        </ResourceDictionary>
    </Window.Resources>
    <StackPanel>
        <StaticResourceExtension ResourceKey="moreContent" />
        <StaticResourceExtension ResourceKey="content" />
        <StaticResourceExtension ResourceKey="moreContent" />
    </StackPanel>

Ribbon.xaml:
    <StackPanel x:Key="content" x:Shared="false">
        <TextBlock Text="From Ribbon" />
    </StackPanel>
</ResourceDictionary>

No comments: