I have a resource dictionary in my WPF application which contains the style information for the various controls.
Can it be used like the way we use in CSS in HTML? For example
p
{
margin:20px;
font:Tahoma;
}
this applies to all "p" tags in HTML. We dont have to specifically mention that in the HTML for "p" tag.
Is the same approach applicable in WPF, or do we have to specifically
mention the style
<TextBlock Text="Test" Style="{DynamicResource SomeTextblockStyle}" />
in the XAML
You can certainly set a default style for each type. You can do this within your Generic.xaml, note that I am not providing a key.
<Style TargetType="{x:Type Button}">
<Setter Property="Height" Value="25"/>
<Setter Property="Foreground" Value="White"/>
</Style>
This will style every instance of a Button within your application as such.
If you were go to a XAML file and define an instance of a Button, overriding the Foreground value, that local instance will take precedence over the global style.
<Button Foreground="Black"/>
You can set style like using key
<Style TargetType="{x:Type TextBlock}" x:Key="myStyle">
<Setter Property="Margin" Value="20"/>
<Setter Property="FontFamily" Value="Tahoma"/>
</Style>
And in the Window.Xaml
<TextBlock Text="Hello" Style="{DynamicResource myStyle}"/>
Related
I am doing small WPF app for my own using Visual Studio, C#, .NET Standard and WPF in this specific project.
I have defined style for all TextBlocks and TextBoxes in Applications.Resources like below.
<Application.Resources>
<Style TargetType="TextBox">
<Setter Property="FontSize" Value="10"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="10"/>
</Style>
</Application.Resources>
Then in main window I have a grid which contains some buttons.
<Grid>
<Grid.Resources>
<Style TargetType="Button">
<Setter Property="FontSize" Value="50" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="50"/>
</Style>
</Grid.Resources>
<Button Grid.Column="0" Content="DASHBOARD" Command="local:CustomCommands.ShowDashboard"/>
</Grid>
I would like to set for the textblocks/textboxes in this specific buttons a wider font.
I tried for many different syntax but could not manage it. I tried also do define x:Key for this style in Grid.Resources and use it in this specific Button control. This wasn't work either.
Can anyone let me know which way should I let know my application that text in this buttons would have bigger font size?
The TextBlock created for string contents by the ContentPresenter inside the Button template doesn't apply the locally-defined resources, i.e. those in your Grid.
The easiest way to solve your problem would be to explicitly define a TextBlock as the Button's content.
<Grid>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="50"/>
</Style>
</Grid.Resources>
<Button Grid.Column="0" Command="local:CustomCommands.ShowDashboard">
<TextBlock Text="DASHBOARD" />
</Button>
</Grid>
I am trying to get to grips with WPF Styles.
I was wondering if it is possible to define one Style key and then describe how it should be applied to different TargetTypes.
This approach is not working for me. I get an error message to say that "TargetType 'TextBlock'" does not match the Element "Image".'
It seems strange that every style:type combination needs it's own key name. I am doing something wrong? Is it completely the wrong approach?
e.g. in the Window.xaml:
<TabControl TabStripPlacement="Bottom">
<TabItem Content="{Binding UserContent}">
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Image Source="users_24.gif" Style="{StaticResource TabHdr}"/>
<TextBlock Text="{x:Static r:Messages.Tab_Users}" Style="{StaticResource TabHdr}"/>
</StackPanel>
</TabItem.Header>
</TabItem>
</TabControl>
and in the Resources.xaml
<Style x:Key="TabHdr" TargetType="{x:Type Image}">
<Setter Property="Width" Value="20"/>
<Setter Property="Height" Value="20"/>
<Setter Property="Margin" Value="2, 1, 2, 1"/>
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="5, 1, 1, 1"/>
</Style>
You can do that if you plan on explicitly setting the Style as you are (i.e. they are keyed styles - implicit styles are always found using the exact type of the class). You just have to set the TargetType to be the lowest base type that defines all the dependency properties you are setting. So in your case you are setting properties that are defined on FrameworkElement so you can just set the TargetType to FrameworkElement.
<Style x:Key="TabHdr" TargetType="FrameworkElement">
<Setter Property="Width" Value="20"/>
<Setter Property="Height" Value="20"/>
<Setter Property="Margin" Value="2, 1, 2, 1"/>
</Style>
Note: If however you wanted to set something like Background (which is defined on Control) then you wouldn't be able to share that style with Image/TextBlock (which don't derive from Control) but you could create a style where the TargetType is Control in that case. You could even set the BasedOn of that style to the style you have for FrameworkElement so you can still share the other settings. E.g.
<Style x:Key="ctrl" TargetType="Control" BasedOn="{StaticResource TabHdr}">
<Setter Property="Background" Value="Red" />
</Style>
And then use it on multiple controls. E.g.
<TextBox Style="{StaticResource ctrl}" />
<Button Content="Foo" Style="{StaticResource ctrl}" />
To short answer your question.. you can't!
You are assigning TabHdr style to a TextBlock, but the style is defined as a Image control style. You can't do that.
If all of your control have to have a specific style, you can define a style without a key but with a specific TargetType. For example, in the code you provided, the TextBlock is applied to all TextBlocks.
PS: If you have to create a kind of theme for your application you can inherit and extend a base style using the BasedOn attribute.
I have a WPF application with many windows and user controls, and I'd like to implement standard styles for certain controls that appear throughout the application. As an example, say I need two standard TextBlocks throughout the application: one for large headings, one for small headings. And the only difference between them is the font size, say 36 and 24 respectively. All other properties (color, fontfamily, etc.) could be set by a TextBlock template or global TargetType="{x:Type TextBlock}" styles.
Of course I could create two global named styles that just set the font size and apply those staticresource styles liberally throughout the XAML to my TextBlocks, or at the highest possible level above the TextBlocks that would not interfere with other TextBlocks. But as an alternative, which would remove the requirement for setting the Style tag in many places, is inheriting from TextBlock is a good way to go?
TextBlock controls:
class TextBlockLargeHeading : TextBlock
{
public TextBlockLargeHeading()
{ }
}
class TextBlockSmallHeading : TextBlock
{
public TextBlockSmallHeading()
{ }
}
Global resource:
<Application.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red" />
</Style>
<Style TargetType="MyApp:TextBlockLargeHeading" BasedOn="{StaticResource {x:Type TextBlock}}" >
<Setter Property="FontSize" Value="36" />
</Style>
<Style TargetType="MyApp:TextBlockSmallHeading" BasedOn="{StaticResource {x:Type TextBlock}}" >
<Setter Property="FontSize" Value="24" />
</Style>
</Application.Resources>
Then, to use them anywhere, simply reference the custom textblocks:
<StackPanel>
<MyApp:TextBlockLargeHeading Text="Large" />
<MyApp:TextBlockSmallHeading Text="Small" />
</StackPanel>
Which would create two Red TextBlocks with the appropriate font sizes.
Is this a reasonable approach? Are there any gotcha's if I've got 100's of instances of these, maintainability-wise or otherwise? Is there a better (safer or less code/XAML) approach? Perhaps using User Controls instead?
Thanks!
There's no reason to do all that. Create your styles and use them directly.
....
<Style x:Key="DefaultTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="Red" />
<Setter Property="FontSize" Value="24" />
</Style>
<Style x:Key="LargeTextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource DefaultTextBlockStyle}">
<Setter Property="FontSize" Value="36" />
</Style>
<!-- Style applies to all TextBoxes -->
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource DefaultTextBlockStyle}" />
...
<StackPanel>
<TextBlock Text="Large" Style="{StaticResource LargeTextBlockStyle}"/>
<TextBlock Text="Small"/>
</StackPanel>
How do I change what WPF's idea of the default style for a control is? And why is this happening in the first place? In the below XAML, I declare a Style for Button, and then further declare a new Style that overrides one of the setters called "HugeBut". I would expect that HugeBut is implicitly BasedOn my new un-named style, but apparently it is not;
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="Red">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- badness -->
<Style TargetType="{x:Type Button}" x:Key="HugeBut">
<Setter Property="Foreground" Value="Yellow"/>
</Style>
<!-- works, but I do not want to explicitly set the based-on. -->
<Style TargetType="{x:Type Button}" x:Key="HugeBut" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Foreground" Value="Yellow"/>
</Style>
</Window.Resources>
<Button Content="Regular" />
<Button Content="huge!" Style="{StaticResource HugeBut}"/>
You would expect two red buttons, one with black text and one with yellow, but Style HugeBut inherits all of the values that I did not specify in my unnamed style from the system default theme for Button (Aero in my case).
What can I do to change this behavior?
It appears that the answer is here:
http://wpfthemereplacer.codeplex.com/
From the site description:
This library allows users to provide their own resource dictionaries
to replace the default theme dictionaries loaded by WPF. This makes it
so you don't have to decorate custom styles with
BasedOn="{StaticResource {x:Type ...}}" when your own custom theme is
being used in your application. It also makes it so if you have custom
controls that just provide enhanced capability and don't need to
replace the the style, you don't need to define a new style or
override the DefaultStyleKey when you create the custom control.
This is exactly what I'm looking for. This will allow me to use Styles as they are meant to be used across an app that has been extensively "re-themed", rather than theme-ing by setting global styles (and then deal with tracking down bits of code that are missing BasedOn, or cannot deal with it at all due to WPF bugs and other constraints)
works, but I do not want to explicitly set the based-on.
Well, the framework does not really care if you don't want to, for all i know, you have to.
I have the following style defined in the ResourceDictionary of a Silverlight 4.0 application
<Style x:Key="GridSplitterStyle" TargetType="sdk:GridSplitter">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template" Value="{StaticResource GridSplitterTemplate}" />
</Style>
<ControlTemplate x:Key="GridSplitterTemplate" TargetType="sdk:GridSplitter">
<StackPanel Background="Transparent" Height="32">
<!-- ... -->
</StackPanel>
</ControlTemplate>
When I apply the style on my GridSplitter, the style is found and properly applied. However, when linking the Template property to the ControlTemplate defined in the same dictionary file, the following error comes up:
Cannot find a Resource with the Name/Key GridSplitterTemplate
How come Silverlight can find the style but not the template? They are located in the same file...
Static resource references are resolved during Xaml parsing. As a result you cannot have use forward referencing.
Place the control template above the style in document order so that the parser finds "GridSplitterTemplate" first. Then when "GridSplitterStyle" references it, the parser will be able to find it.