none
WPF Style Inheritace - how to automatically inherit style from base control

    Question

  • Hi!
    I'm writing TabControl descendant:

    public class MyTabControl:TabControl
    {
    ...
    }

    I want my control to look 100% same like original TabControl for any theme.
    At first I have trying to write something like:

    static MyTabControl()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(MyTabControl), new FrameworkPropertyMetadata(typeof(TabControl)));
            }

    It doesn't help.

    Hext time I tryed to write something like
    <Style TargetType="{x:Type local:MyTabControl}"  BasedOn="{StaticResource {x:Type TabControl}}"    />

    into Window.xaml
    It works but I doesn't want to write this every time. Those controls are in some assembly.  And I tried to create Generic.xaml under Themes folder:
    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Controls="clr-namespace:aaa">
        <Style TargetType="{x:Type Controls:UnselectableTabControl}"
               BasedOn="{StaticResource {x:Type TabControl}}"
              >
        </Style>
    </ResourceDictionary>

    but it doesn't help...




    Thursday, April 24, 2008 4:29 PM

Answers

  • The Style get messed up because you explicitly load the aero theme dictionary and merge it into application level, the Styles within the explicitly loaded theme dictionary will be treated as explicit styles, and they will override the default theme styles coming from the theme dictionary (in your case, it will be PresentationFramework.Classic.dll) which matches the system theme of your OS.

    You could put below Style definition at App.Resources resource dictionary to workaround this issue:
    <Style x:Key="{x:Type local:MyButtonDemo}" BasedOn="{StaticResource {x:Type Button}}"/>

    Note that you need to add this style to the App.Resources dictionary after loading and merging the Aero theme dictionary.

    hope this helps

    Tuesday, April 29, 2008 6:40 AM
  •  dimzon wrote:

    But the main question - is it possible to avoid this inclusion for this scenario.


    No, because when merging dictionary in the way you did above, you were effectively override the theme style coming from theme dictionary, the implicit style look up will look up style based on the Type object as a key. That's why you need to explicitly specifiy a Typed key aka x:Key="{x:Type cc:MyButton}".

    Hope this helps
    Wednesday, April 30, 2008 3:06 AM

All replies

  • When overriding a Control, as long as you don't override its default style, the derived control will pick up the style of the base control, so basically you can simply do this:

    public class MyTabControl : TabControl
    {
    }

    And you are done with it.

    Hope this helps
    Monday, April 28, 2008 4:33 AM
  • Code Snippet

    using System;

    using System.Windows;

    using System.Windows.Controls;

    public class MyButtonDemo: Button

    {

    [STAThread]

    public static void Main(string[] a)

    {

    var application = new Application();

    var uri = new Uri(

    "PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component\\themes/aero.normalcolor.xaml",

    UriKind.Relative);

    application.Resources.MergedDictionaries.Add(Application.LoadComponent(uri) as ResourceDictionary);

     

    var w = new Window

    {

    Title = "MyButtonDemo - window",

    SizeToContent = SizeToContent.WidthAndHeight

    };

    var sp = new StackPanel();

    sp.Children.Add(new Button { Content = "WPF Button"});

    sp.Children.Add(new MyButtonDemo { Content = "WPF Button Descendant" });

    w.Content = sp;

    application.Run(w);

    }

    }

     

     

     

     

    produce such window:   ( http://img247.imageshack.us/img247/7678/14628692dy0.png )
    Monday, April 28, 2008 12:27 PM
  • The Style get messed up because you explicitly load the aero theme dictionary and merge it into application level, the Styles within the explicitly loaded theme dictionary will be treated as explicit styles, and they will override the default theme styles coming from the theme dictionary (in your case, it will be PresentationFramework.Classic.dll) which matches the system theme of your OS.

    You could put below Style definition at App.Resources resource dictionary to workaround this issue:
    <Style x:Key="{x:Type local:MyButtonDemo}" BasedOn="{StaticResource {x:Type Button}}"/>

    Note that you need to add this style to the App.Resources dictionary after loading and merging the Aero theme dictionary.

    hope this helps

    Tuesday, April 29, 2008 6:40 AM
  • Yes, placing <Style x:Key="{x:Type local:MyButtonDemo}" BasedOn="{StaticResource {x:Type Button}}"/> helps.

    But the main question - is it possible to avoid this inclusion for this scenario.

    Actually I'm developing some control library wich will be used across multiple projects in own company. And I don't want force every project to include such style for EVERY control used . So I need 100% same behavior as built-in WPF controls have.

    Thanks a lot for Your help!

     

    Tuesday, April 29, 2008 10:56 AM
  •  dimzon wrote:

    But the main question - is it possible to avoid this inclusion for this scenario.


    No, because when merging dictionary in the way you did above, you were effectively override the theme style coming from theme dictionary, the implicit style look up will look up style based on the Type object as a key. That's why you need to explicitly specifiy a Typed key aka x:Key="{x:Type cc:MyButton}".

    Hope this helps
    Wednesday, April 30, 2008 3:06 AM