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);
Related
I'm creating the custom control. And suddenly faced a question: why to put control's style separately from the control?
I mean that using the standard way you must: derive from base control (for example, from TextBox) and add a style for it in general.xaml.
But why can't we do just like this:
<TextBox x:Class="CustomTest.CoolTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TextBox.Style>
<Style>
<Setter Property="TextBox.FontSize" Value="20" />
</Style>
</TextBox.Style>
</TextBox>
And code-behind:
public partial class CoolTextBox : TextBox
{
public CoolTextBox()
{
InitializeComponent();
}
}
Update #1
I'm not writing my own library but creating a custom control inside my main executable. Application support themes but they differ only by colors. So each theme is a set of brush resources and my style will refer them using DynamicResource.
What I want to know is the drawbacks of that solution. I mean performance, simplicity of usage and etc.
WPF allows changing themes at runtime, means the style shall be stored separatly from the controls. Futhermore the control shall be lookless when designining in order to other programmers to have their custom styles though somewhere there should be a default style which must be stored separatly in a Generic.xaml file. If your app doesn't support changing themes then you can define the style wherever you wish.
If you are writing a library of custom controls I suggest you to stick to standards.
Here is a link how shall a custom controls be created:
http://wpftutorial.net/HowToCreateACustomControl.html
In addition to dev hedgehog's answer about performance, I found the following drawbacks:
Style object is own for each instance of control. So you end up with number of clones of the same Style object.
You cannot override style using BasedOn property. Only completely replace is possible.
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}>
We're writing a custom subclass of TextBox where we need to change only some basic parts of the style. Now we know when you subclass Control, normally you're supposed to change the metadata like this...
public class EnhancedTextBox : TextBox {
static EnhancedTextBox() {
// Commenting this line out lets this use the default TextBox style.
DefaultStyleKeyProperty.OverrideMetadata(
typeof(EnhancedTextBox),
new FrameworkPropertyMetadata(typeof(EnhancedTextBox)));
}
}
This changes the key used for that subclass type to be the type itself, which means it no longer gets the default TextBox style. No biggie... we just comment that line out and it again works since the key is still set to the value used by TextBox directly.
However, we're wondering if we did want to change a few things in the style, but not the entire style, we could simply create a new style and set its BasedOn property... but what do we set there? We don't want to have to pull out the XAML manually and create a new style, give it a key, then use a StaticResource, but we haven't found out what we could set there to say 'This is based on the TextBox style.
I'm hoping its something simple but again, we haven't found it. Can anyone help?
And just like that... I found it. Man, kicking myself that it was this obvious and I missed it!
<Style TargetType="{x:Type local:EnhancedTextBox}"
BasedOn="{StaticResource {x:Type TextBox}}">
....
</Style>
Found it here... WPF style basedon current
Hey, I am creating a Custom Control i WPF inheriting from the ListView. However, I want it to look exactly as the already existing ListView.
Is there a way To use the default ListView Template in a Custom Control without rewriting it in xaml? I do have a Generic.xaml file with the new control added, but I should no need to rewrite the template code.
Thanks
EDIT: I also want to keep it as DRY as possible without repeating (making a mess) the code.
If you subclass the ListView, them your subclassed control will use the ListView Template. That's it! You do not have to do anything!
The Template used by a control is defined by its DefaultStyleKey dependency property. If you want to change the template of your control, set this property as follows:
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl),
new FrameworkPropertyMetadata(typeof(MyControl)));
However, if you do not set this property, it will use the value set by the superclass.
I think the problem is that you have used "Add New Item" => "Custom Control" to create you control then changed the class it extends. Instead of doing this, just add a new C# class and extend ListView.
<Style TargetType="{x:Type local:MyControl}" BasedOn={StaticResource {x:Type ListView}}" />
Anyone got any neat solutions to prevent a Silverlight ChildWindow being moved?
thanks,
Mark
I'm not sure you'd call this neat but...
Create yourself a new Templated control and call it ImmovableChildWindow.
Modify the class it inherits from to be ChildWindow.
Open Themes/generic.xaml you will find an initial style for the ImmoveableChildWindow
In the Silverlight documentation you'll find the existing template for a ChildWindow at ChildWindow Styles and Templates.
Note the existing TargetType value for the ImmovableChildWindow style.
Copy'n' paste the whole default style for a ChildWindow from the documentation into your themes/generic.xaml file.
Replace TargetType for this copy to the same value as the exiting ImmovaleChildWindow style.
You can now delete the initial style. Leave only the large copy of ChildWindow style now targeting ImmovableChildWindow.
Find within the Template setter change the TargetType of to the same value as the style TargetType
Search through the template and find a Border with the name Chrome. Delete the x:Name="Chrome" attribute. (This is what we are really after).
Now when you create a new ChildWindow item it will by default inherit form ChildWindow, if you want it to be immovable you need modify it to inherit from ImmovableChildWindow instead (change the base type in the code-behind and the root tag name in the xaml).
The ChildWindow attaches events to the FrameWorkElement with the name "Chrome" which enables the child window to be moved about. However being a well-behaved templated control, if it can't find a FrameworkElement called "Chrome" it just continues to work without that feature.
Not Required to Create new class, instead
Copy the style from: http://msdn.microsoft.com/en-us/library/dd833070%28VS.95%29.aspx
Give x:key="stylename"
In Construtor of Childwindow, paste following code before InitializeComponent:
this.Style = App.Current.Resources["childWindow"] as Style;
above solution resolved my issue
Maybe you can try this simple way to do that:
Create a Grid to warp all the content in your ChildWindow.
<Grid Margin="0">
<!--Your ChildWindow. Canvas, Grid, Textblock...Whatever-->
</Grid>
Since the Grid has a 0 margin, you can not click it and move it.