Search code examples
c#wpfxamlresourcedictionary

Splitting Generic.xaml up in Control Library


My Generic.xaml starts growing pretty large and i am searching for ways to split it up.

The first thing i tried was the most obvious to me: use ResourceDictionary.Merge to do the trick. However, when doing this, the styles set in those XAML files are not applied.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:SimplifySoft.Controls">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/MyAssembly;component/Path/Control1.xaml"/>
        <ResourceDictionary Source="pack://application:,,,/MyAssembly;component/Path/Control2.xaml"/>
        <ResourceDictionary Source="pack://application:,,,/MyAssembly;component/Path/Control3.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Naturally, i first expected a mistake of mine in configuration of those. To confirm wether it was, i altered the file to something like this:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:SimplifySoft.Controls">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary>
            <SolidColorBrush x:Key="MySolidColorBrushKey" Color="Red" />
        </ResourceDictionary>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

as this neither is working, i am now here and asking:

How to properly Split up the generic.xaml file

Please note that using just the plain ResourceDictionary works perfectly fine and as expected, but due to the size of the file i start getting trouble editing the default styles.

Also note that the files refered in the Source parameter are having the Build Action Resource and are ResourceDictionaries themself. The Generic.xaml has the Build Action Page

Thanks for your time :)


Solution

  • I'm doing exactly what you tried to do, and never had an issue with that. So as a quick test, I changed Build Action on one of the ResourceDictionaries to Resource, rebuilt the project (simply building didn't do it), and got a XamlParseException - the control whose default style is in ResourceDictionary could not be initialized.

    So what changes when you change the Build Action from Page to Resource?

    In Visual Studio, when you add a new Window, NavigationWindow, Page, FlowDocument, or ResourceDictionary to a project, the Build Action for the markup file will default to Page.

    When a project with Page items is compiled, the XAML items are converted to binary format and compiled into the associated assembly. Consequently, these files can be used in the same way as typical resource files.

    Note: If a XAML file is configured as a Resource item, and does not have a code-behind file, the raw XAML is compiled into an assembly rather than a binary version of the raw XAML.

    More details on resource files on Microsoft docs.

    Assuming your Source paths are correct (I keep mine in Themes folder, so I have Themes where you have Path), and (if you derived from a standard control) your custom controls have their static constructors with DefaultStyleKeyProperty.OverrideMetadata, you only need to revert the Build Action to Page.

    Note: Second code example can't work as theming is not skinning. Generic.xaml is basically used to supply default styles for custom controls (more about it in this SO question).