WPF Custom Control based on TabItem and Themes - wpf

I have a Generic.xaml theme created that sets styles for all common controls, including TabItem
This them is applying ok to all controls in the application
When I create a TabItem control and display it, it gets the Theme OK.
TabItem t = new TabItem();
t.Header = "Normal";
MainContentControl.Items.Add(t);
However when i create a Custom Control based on TabItem
public partial class ClosableTab : TabItem
and display it
ProActive.LocalControls.ClosableTab ct = new ProActive.LocalControls.ClosableTab();
ct.Header = "COMP";
MainContentControl.Items.Add(ct);
The theme is ignored.
I have tried over writing its defaultstyle using
DefaultStyleKeyProperty.OverrideMetadata(typeof(ClosableTab), new FrameworkPropertyMetadata(typeof(TabItem)));
Why if my custom control is based on a TabItem is the theme not also applying to it?

DefaultStyleKey is only used for looking up theme styles. Theme styles must be defined in the assembly defining the control or in a related assembly according to the ResourceDictionaryLocation specified in the control assembly. The TabItem themes are in PresentationFramework.Aero and WPF will look for ClosableTab themes in your assembly, so even if they have the same key it won't find them. Here is a good description of how WPF looks up theme styles.
Implicit styles will always be looked up using the actual type of the control, so if you have a <Style TargetType="TabItem"> in your resource dictionary then it won't affect a ClosableTab.
The easiest way to have ClosableTab inherit the implicit style from TabItem is to create an implicit style for ClosableTab and use BasedOn:
<Style TargetType="local:ClosableTab" BasedOn="{StaticResource {x:Type TabItem}}" />

Related

Setting implicit style of custom control in WPF

My custom control's default style is defined in Generic.xaml and is working fine.
However, when I try to change the style of my custom control the same way as one can with built in controls nothing happens. In App.xaml I am trying to change the default style of my control by doing the following:
<Style TargetType="{x:Type my:CustomControl}">
<Setter Property="Background" Value="Red"/>
</Style>
If I set the x:key property of the above style and reference this style using this key all works fine.
Is it correct that the above styling method only works for built in controls and does not work for custom controls, or am I just doing something wrong? Is there a workable solution to achieve this type of styling for custom controls?
Update
In this situation my custom control is derived from System.Windows.Window.
I finally managed to get implicit styling for my custom control to work. Apparently implicit styling might not work for derived controls as the style is not automatically being applied to the control. In order to achieve this one has to manually set the resource reference. My custom control now looks like this:
public class CustomControl : Window
{
static CustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl), new FrameworkPropertyMetadata(typeof(CustomControl)));
}
public CustomControl()
{
SetResourceReference(StyleProperty, typeof(CustomControl));
}
}
Yes, you are correct. Generic.xaml is used for custom controls, and App.xaml for application-wide resources (including styles for built-in controls). Specifying TargetType for a custom control in App.xaml will not work. So using explicit styles (with x:Key) seems to be the easiest solution.

Derive from Control and then allow others to apply a style

I have derived a new control from Control base class and set the DefaultStyleKeyProperty in the static constructor so that the appropriate style from Generic.xaml is used to defined the ControlTemplate. This all works fine and I get the expected appearance of several buttons etc.
Now I want to add some Style instances that customize the settings of my new control, such as the font and foreground color. But when I assign the style to the custom controls Style property it seems to remove the original default style and so it no longer has any appearance.
This doesn't seem quite right. The TabControl has a default style but you can still assign a Style to the TabControl.Style property that only modifies the Foreground color and it will not remove the rest of the TabControl appearance in the process.
Any ideas what I am doing wrong?
Declare your new style based on the default:
<Style TargetType={x:Type MyControl} BasedOn={StaticResource {x:Type MyControl}>

Reusing existing templates in custom WPF controls

I am creating a custom WPF control class which inherits from ComboBox. As I am just defining behavior, the exiting ComboBox templates are fine for my purposes and I don't want to created a whole set of templates to support different themes. Is there a way to specify that my control uses the existing ComboBox templates?
Give your control a default style and set BasedOn to the default style of ComboBox:
<Style TargetType="{x:Type local:CustomControl1}"
BasedOn="{StaticResource {x:Type ComboBox}}">
</Style>
This will inherit the template setter from the ComboBox default style.
You don't have to do anything. If your control inherits from ComboBox and you don't override the DefaultStyleKey property, it will use the same style as ComboBox (thus the same template)

How to apply styles to the whole silverlight application?

I have created two different grid background and radio button style in my
App.xaml.
User can select any style to change the look of the page i.e: Changing the background and style of the radiobutton.
Now When I click on the raduio button the application navigates to another page and the style disappears.
Is there a way to Set the style in application level or I need to store the styleVar as Global Var and check on the second page load and then apply the styles as per the styleVar.
Yes like Jeff Wilcox said Implicit styling is a new thing in Silverlight 4. So if you want to create a style that is the default for all the controls of that type in the range XAML file or the whole application if placed in App.xaml you would leave out the x:Key attribute.
<Style x:Key="ButtonStyle" TargetType="Button">
To use ButtonStyle you would have to write:
<Button Content="A button" Style="{StaticResource ButtonStyle}" />
Leaving out the x:Key would allow you to use ButtonStyle as default.
<Style TargetType="Button">
<Button Content="A button with style that has no x:Key value" />
Now if you'd need to create a button that doesn't have this default style, you can set the Style property of that button to be x:Null or override by setting a named style to that button.
<Button Content="Default Silverlight button" Style="{x:Null}"/>
Another new thing with Styles in Silverlight 4 is that you can create new styles that are based on existing ones. Although it wasn't your question I'll give an example:
<Style TargetType="Button" BasedOn="{StaticResource BasedStyle}">
About implicit styling in the docs: http://msdn.microsoft.com/en-us/library/system.windows.style%28VS.95%29.aspx
Implicit Styles
In Silverlight 4, you can set styles
implicitly. That is, you can apply a
certain style to all elements of a
certain type. When a resource
is declared without an x:Key value,
the x:Key value assumes the value of
the TargetType property. If you set
the style implicitly, the style is
applied only to the types that match
the TargetType exactly and not to
elements derived from the TargetType
value. For example, if you create a
style implicitly for all the
ToggleButton controls in your
application, and your application has
ToggleButton and CheckBox controls
(CheckBox derives from ToggleButton),
the style is applied only to the
ToggleButton controls.
BasedOn Styles
Starting with Silverlight 3, it is
possible to build a new style based on
an existing style. You can do this
using the BasedOn property. This
reduces the duplication of code and
makes it easier to manage resources.
Each style supports only one BasedOn
style. For more information, see the
BasedOn property.
Just leave off the x:Key part of the Style, inside App.xaml. This is a new feature for Silverlight 4.
Place the styles in question in the App.xaml file. The application objects Resources property makes Styles and other resources available across the entire application.

WPF style problem with custom control and textbox-derived class

I had the following situation:
main application has app.xaml, which sets the Style for TextBox controls
a custom control is implemented in a separate DLL, and uses several TextBox controls
The main application's TextBox Style is applied to the custom control's TextBox controls. Cool!
My problem comes in because I need to use a class derived from TextBox in the custom control. Now the main app's TextBox Style is no longer applied. Can the custom control DLL have something like "app.xaml" where I can set the style for all my derived TextBox controls? Or can the main application somehow set the Style for all TextBox-derived classes?
Thanks!
You can set the BasedOn property of the custom TextBox style to the base style. Should automatically derive from whichever base style it inherits, in this case your application-level style.
<Style x:Key="CustomControlStyle" TargetType="{x:Type local:CustomControl}" BasedOn="{x:Type TextBox}">

Resources