Derive from Control and then allow others to apply a style - wpf

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}>

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.

Setting FontFamily of TextBox applicationwide

I have a big project at hand which involves a large amount of views and usercontrols. Additionaly, I want to set the FontFamily of every element to a certain font.
This works with most of the usercontrols like textBlocks, buttons and labels. Sadly this does not hold for textBoxes. They remain unchanged.
Before I create the whole GUI, I am overriding most of the metadata for elements containing text:
TextElement.FontFamilyProperty.OverrideMetadata(typeof(TextElement),
new FrameworkPropertyMetadata(new FontFamily("Calibri")));
TextBlock.FontFamilyProperty.OverrideMetadata(typeof(TextBlock),
new FrameworkPropertyMetadata(new FontFamily("Calibri")));
After a bit of searching, I found this article using the same method: http://blog.davidpadbury.com/
It clearly states at the end:
"In the above image you’ll see that we’ve successfully change the font on the text blocks, labels and buttons. Unfortunately the font inside the TextBox remains unchanged, this is due to it receiving it’s FontFamily property from it’s base class Control. Control adds itself as an Owner of the TextElement FontFamilyProperty but specifies it’s own metadata which we are then unable to override."
It also suggests to create a control template, which then sets the fontFamily. Is there another way? I want to set the fontFamily programmatically at the start without using XAML or creating a controlTemplate and using it as a base template for every textBox.
Thanks in advance.
You can declare a Style without the x:Key property and it will apply to all controls of that type:
<Style TargetType="{x:Type Control}">
<Setter Property="FontFamily" Value="Calibri" />
</Style>
Alternatively, you can simply set this on the MainWindow definition which will affect most elements:
<Window TextElement.FontFamily="Calibri" ...>
...
</Window>
Ahhh... I've just noticed your condition of not using xaml... sorry, I should have looked closer the first time.
UPDATE >>>
After a little research, it seems that you can do this in code like this:
Style style = new Style(typeof(TextBlock));
Setter setter = new Setter();
setter.Property = TextElement.FontFamilyProperty;
setter.Value = new FontFamily("Calibri");
style.Setters.Add(setter);
Resources.Add(typeof(TextBlock), style);
Unfortunately, you'd have to do other Styles for other types of controls too.
UPDATE 2 >>>
I just thought of something... that previous example just set the Style into the local Resources section which would be out of scope for your other modules. You could try setting the Style to the Application.Resources section which has global scope. Try replacing the last line of the code example above to this:
App.Current.Resources.Add(typeof(TextBlock), style);

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