25

I made a class library assembly in which I created custom controls, and I defined the default styles in the generic.xaml file.

It seems this is a quite common problem, as long as many people are posting about it. However I couldn't find any useful answer for my case.

  • the generic.xaml is in the Themes folder.
  • the generix.xaml file Build Action is set to Page.
  • the ThemeInfo is properly defined in my AssemblyInfo.cs.

In my test application, if I manually merge the generic.xaml file from my custom controls assembly into the application App.xaml file like this:

<Application.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="/MyControlsAssembly;component/Themes/generic.xaml"/>
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

then the custom controls are properly themed, but if I do not manually merge the generic.xaml, the controls appear with the default Windows theme.

Could you please tell me what am I forgetting and/or doing wrong ?

Additional info:

  • My ThemeInfo assembly attribute is defined as follow:

    [assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly, ResourceDictionaryLocation.SourceAssembly)]

    (Note: the result is just the same with any combination of parameters for the ThemeInfo attribute)

  • There are two others .xaml files beside the generic.xaml file in the Themes folder.

  • There is a subfolder in the Themes folder that itself contains another .xaml file.
Sebastien ROBERT
  • 596
  • 1
  • 5
  • 10
  • 4
    Do you still have the DefaultStyleKeyProperty set in a static constructor on your custom controls? – Nogusta Jun 22 '12 at 03:47
  • 1
    Any luck figuring this one out? I have almost the same exact thing going on with my custom controls assembly. If I add a reference in App.config to the generic.xaml file then the controls are themed. If I leave this out I get nothing. – Mike G Feb 15 '13 at 19:19
  • Does this link apply? http://social.msdn.microsoft.com/Forums/vstudio/en-US/2e1fb162-e828-4fd9-832f-d2791c1980b4/isnt-genericxaml-supposed-to-loaded-automatically I took am facing the same problem, and I think this is the root cause – Robert Snyder Aug 26 '13 at 14:47
  • 1
    Any solution to this issue? I'm experiencing the exact same thing, and following the steps suggested here or in http://blogs.magnatis.com/tim/dude-wheres-my-default-style does not help. I need to include the merge in App.xaml as in this post. – bigfoot Nov 01 '13 at 23:00
  • 2
    Adding ThemeInfo in AssemblyInfo.cs of the control library did the trick for me. I used (None, SourceAssembly). – Heiner Mar 05 '14 at 10:15
  • I know it sounds silly, but **are you sure your theme is located at [PROJECT]\Themes\Generic.xaml?** I had the same problem, my themes did not load and it turned out because I had an extra folder in the path ([PROJECT]\MySubProject\Themes\Generic.xaml). – Shakaron Jun 24 '15 at 13:32

5 Answers5

18

To apply default styles in Themes\Generic.xaml in my custom controls library I decided to seek inspiration from a well established open source controls library (MahApps). This project gives you a really good example of how to structure and layout a custom controls library.

Cut a long story short, to get your default styles in Themes\Generic.xaml you need to include the following in the AssemblyInfo.cs file in your custom controls library:

[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

In my case, my custom controls AssemblyInfo.cs looked something like:

using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Markup;

[assembly: AssemblyCopyright("...")]
[assembly: ComVisible(false)]

[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0.0")]
[assembly: AssemblyTitleAttribute("...")]
[assembly: AssemblyDescriptionAttribute("")]
[assembly: AssemblyProductAttribute("...")]
[assembly: AssemblyCompany("...")]
JT_
  • 503
  • 5
  • 9
14

You need the following line in your custom control constructor:

public class MyCustomControl : Control
{
    static MyCustomControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
    }
}

Then if you have a generic.xaml file inside themes folder, with the following sample style:

<Style TargetType="{x:Type local:MyCustomControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyCustomControl}">
                <Border>
                    <Label>Testing...</Label>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Now the style will get automatically applied without any extra merging.

Eternal21
  • 4,190
  • 2
  • 48
  • 63
  • This does not work for me. Look at my comment on the initial question – bigfoot Nov 01 '13 at 23:05
  • Start with a blank solution and see if you can get it to work from there? – Eternal21 Nov 02 '13 at 02:58
  • That is what I am doing. I am deriving from Xceed Data Grid. If I create a new MyControl : Control or MyButton : Button, it works. Perhaps it is Xceed theme support that comes into play here, and I need to look into their tutorials on themes, or simply accept the merge dictionary in my application. Unless other ideas surface. – bigfoot Nov 02 '13 at 12:54
1

In My case I forget to remove the x:Key from <Style> tag.

Wrong:

<Style TargetType="controls:IpTextBox" x:Key="MyControlStyle">

Correct:

<Style TargetType="controls:IpTextBox">
Artem
  • 487
  • 1
  • 8
  • 19
0

Not sure if this works in WPF, but it works for me in Silverlight:

Constructor:

public class MyCustomControl : Control
{
    static MyCustomControl()
    {
        this.Style = (Style)Application.Current.Resources["MyCustomControlStyle"];
    }
}

Style:

<Style x:Key="MyCustomControlStyle" TargetType="{local:MyCustomControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{local:MyCustomControl}">
                <Border>
                    <Label>Testing...</Label>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
MikeF
  • 49
  • 5
0

I was having the same problem due to the following attribute in the custom control assembly:

[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]

Changing UltimateResourceFallbackLocation.Satellite to UltimateResourceFallbackLocation.MainAssembly or removing the second parameter completely fixed the problem for me (you can also remove the attribute if you do not need to define the neutral language of your assembly).

Jorbr
  • 11
  • 3