2

I have a custom control (i.e. class derived from System.Windows.Control) and I want to set a default style for it. I know that it is possible to do that by creating themes/generic.xaml and defining the style there. I have done that before and it works.

However, because the style is rather trivial (it is just a dummy rectangle to allow quick mockup), I would like to define the default style in code-only, so that I can keep it close to the class definition and avoid file clutter with the generic.xaml. This is what I have done so far:

    static Trailer()
    {
        // just there to be able to test it alternatively with generic.xaml
        FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(Trailer), new FrameworkPropertyMetadata(typeof(Trailer)));

        // define the template with dummy geometry
        ControlTemplate DefaultTemplate = new ControlTemplate(typeof(Trailer));
        FrameworkElementFactory rectFact = new FrameworkElementFactory(typeof(Rectangle));
        rectFact.SetValue(Shape.FillProperty, new DynamicResourceExtension(SystemColors.ControlLightBrushKey));
        DefaultTemplate.VisualTree = rectFact;

        // define the style
        Style DefaultStyle = new Style {TargetType = typeof (Trailer)};
        Setter setter = new Setter();
        setter.Property = Control.TemplateProperty;
        setter.Value = DefaultTemplate;
        DefaultStyle.Setters.Add(setter);

        // register the style in application resources
        Application.Current.Resources.Add(typeof(Trailer), DefaultStyle);
    }

This works in a very simple test application, but it fails in a more complex setting with other styles/templates where the Control stays empty (default Control style). I haven't been able to figure out what causes the interference, but I take it as evidence that I haven't actually set the default style of my Control with the above code.

Where do I have to set my style, if not in the application resources, in order to get the same behavior as with generic.xaml?

oliver
  • 2,771
  • 15
  • 32
  • There is no code behind replacement for a default Style in Themes/Generic.xaml. See e.g. [this question](https://stackoverflow.com/q/1228875/1136211) for some background info. – Clemens Apr 06 '18 at 19:39

1 Answers1

3

After pondering deeply about this problem and recapitulating my (beginner's) knowledge of dependency properties, I found the simple solution, which I have proven to work. I just had to replace

Application.Current.Resources.Add(typeof(Trailer), defaultStyle);

by

FrameworkElement.StyleProperty.OverrideMetadata(typeof(Trailer), 
    new FrameworkPropertyMetadata(defaultStyle));

which is nothing but the official way to change the default value of a DependencyProperty!

I have already thought into this direction, but my mistake was that I expected to find a "DefaultStyleProperty" (in correspondence to the DefaultStylePropertyKey...), but I didn't think about the easier and more natural possibility of changing the default value of the StyleProperty for my class.

I am glad that Microsoft's design once again turned out to be very logical and carefully crafted (Amen...).

Addendum: I have checked the visual trees with WPF inspector. They are identical irrespective of whether I supply a generic.xaml, or use the code-only method above.

As an additional feature of consistency I have added

FrameworkElement.OverridesDefaultStyleProperty.OverrideMetadata(typeof(Trailer), 
    new FrameworkPropertyMetadata(true));

which keeps the default style from being loaded out of generic.xaml if it should ever be there at all. Since I am setting the style for myself anyway, this doesn't actually make a difference. Be careful though, I am not sure if this can cause unwanted side-effects.

oliver
  • 2,771
  • 15
  • 32