WPF style problem - wpf

I am actually using windows classic style in my applications by using the following declaration
<ResourceDictionary Source="/PresentationFramework.Classic;V3.0.0.0;31bf3856ad364e35;component/themes/classic.xaml" />
But whenever i declare a style to any of my controls say to set the font size and font family the appearance of the control also changes to suit the system theme and thus the control loses the classic appearance.
What could be happening?
I tried using
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" >
to see if this helps me in getting back the classic theme. But it doesn't seem to work.

Try if this works
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/PresentationFramework.Classic;V3.0.0.0;31bf3856ad364e35;component/themes/classic.xaml" />
<ResourceDictionary>
<Style x:Key="ExtendedButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Foreground" Value="Red"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Content="click" Height="30" Width="100" Style="{StaticResource ExtendedButtonStyle}"/>
</Grid>

Related

Extend style without setting an x:Key attribute in the base style

I have a file MyButtonStyles.xaml which designs the WPF button. This file uses a style to set some colors and fonts:
<ResourceDictionary xmlns......>
<Style BasedOn="{StaticResource {x:Type Button}} TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="FontSize" Value="22" />
</Style>
</ResourceDictionary>
This button is used in two xaml files. One shows the button as designed in the above style. This happens automatically because the above style has the according TargetType and it does not have an x:Key attribute.
In the other xaml file I use this button as well but the style from above should be extended by another setter property. Doing this by merging the dictionaries and basing on the original style it works:
<ResourceDictionary>
<ResourceDictionary.MergedDictionary>
<ResourceDictionary Source="MyButtonStyles.xaml" />
<ResourceDictionary.MergedDictionary>
<Style BasedOn="ButtonStylesOrig" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Green" />
</Style>
</ResourceDictionary>
But for this I have to add an x:Key attribute (ButtonStylesOrig) to the base style. This means that in the first xaml which uses the button the base style will not be applied any more.
Is there a possibility to extend a style without losing the global scope of it (e.g. without using x:Key)?
This works:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyButtonStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Background" Value="Green" />
</Style>
</Grid.Resources>
<Button Content="Button" />
</Grid>
</Window>
The key is not to override the resource in the same resource dictionary that you merge your base style into:
WPF Using multiple Resource Dictionaries from multiple projects
You can't combine multiple default styles of the same type a single resource scope. However, it is possible to build default styles in nested resource scopes.
Suppose you merge MyButtonStyles.xaml into the App.xaml resources. Then you can place your second style with the additional setter into Window.Resources or other deeper nested resources and it will combine the correct implicit styles.
A more localized example:
<Grid>
<Grid.Resources>
<ResourceDictionary Source="MyButtonStyles.xaml"/>
</Grid.Resources>
<Grid>
<Grid.Resources>
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Green" />
</Style>
</Grid.Resources>
<Button VerticalAlignment="Top" Margin="20">Both styles</Button>
</Grid>
<Button VerticalAlignment="Center" Margin="20">ExampleDictionary style</Button>
</Grid>

How to style heading labels in WPF/Silverlight/XAML?

This seems simple enough, but I'm having difficulty finding an answer.
I have a WPF window that requires use of headings and sub-headings for different areas. Of course I could include the stlying inline for each element, but I'd really like to keep the styling separate. What's the right way to semantically differentiate the various heading / sub-heading / "normal" label classes so that they can be properly styled in a separate XAML document?
Thanks!
You could just set styles for each of the "label classes" you want in a resource dictionary as follows:
<Style x:Key="heading" TargetType="Label">
<Setter Property="FontSize" Value="24" />
</Style>
<Style x:Key="subHeading" TargetType="Label">
<Setter Property="FontSize" Value="16" />
</Style>
<Style x:Key="normal" TargetType="Label">
<Setter Property="FontSize" Value="12" />
</Style>
And then in your views, you would just have to call the resource and use it as follows:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="Resources/MyResources.xaml">
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Label Style="{StaticResource heading}" Content="This is a heading!" />
</Grid>

WPF default themes and custom styles not working together

Hey, I have a WPF application targeted at XP machines. The problem is that we wish to run with a WPF XP luna theme rather than classic and most of our clients run in classic mode. Our clients are all internal, it's just that their machines were configured with XP classic.
In theory, this is as simple as adding this to the application:
<ResourceDictionary Source="/PresentationFramework.Luna, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35,
ProcessorArchitecture=MSIL;component/themes/luna.normalcolor.xaml" />
In practice, as soon as a touch any of the styles (say add a margin to TextBox), they styles seem to revert back to classic theme.
This displays correctly (Style Luna):
<TextBox Width="80" Height="20" />
This displays correctly (Style Luna):
<TextBox Width="80" Height="20" Background="Brown">
This displays incorrectly (Style Classic), note it does not matter now many nodes there are in the style block - zero is enough to confuse things:
<TextBox.Style><Style></Style></TextBox.Style></TextBox>
Long and short, overriding the default OS theme seems to preclude further use of styles. What am I missing here?
See the select answer for 80% of the story. The full story is this: I must supply the ‘BasedOn’ setting as well. Unfortunately, this means we can not override, say textbox, without causing a loop. Defining:
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Margin" Value="0,2,0,2" />
:
</Style>
would result in the error: "a loop was detected in the property expression".
The way I chose to get around this was to force named styles everywhere. For example:
<Style x:Key="TextBase" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Margin" Value="0,2,0,2" />
:
</Style>
<Style x:Key="Text25Chars" TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBase}">
<Setter Property="Margin" Value="0,2,0,2" />
:
</Style>
try this:
<TextBox>
<TextBox.Style>
<Style BasedOn="{StaticResource {x:Type TextBox}}">
</Style>
</TextBox.Style>
</TextBox>
edit:
forgot the TargetType, this works for me:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary Source="/PresentationFramework.Luna, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35,
ProcessorArchitecture=MSIL;component/themes/luna.normalcolor.xaml" />
</Window.Resources>
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Foreground" Value="Blue" />
</Style>
</TextBox.Style>
tototototottototo
</TextBox>
</Window>

Setting an Elements.Resource Style using BasedOn within a Resource Dictionary

I have a Resource Dictionary that I am using to define the look-and-feel (style) for my application.
I have just created another Resource Dictionary that contains DataTemplates that I am using on several different screens (and even multiple times within the same screen) to display my business objects.
I would like to change some of the default styles within my DataTemplates so that the controls fit better; however I would like the controls to inherit the same style as the rest of the screen. So, naturally I want to use the BasedOn property for this task.
The problem that I am having is that I'm not sure what to set the BasedOn property to.
For example, in the resource dictionary that contains my styles (called "myStyle.xaml") I have:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:primatives="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Label}">
<Setter Property="Foreground" Value="#F5F5F5" />
<Setter Property="FontSize" Value="12"></Setter>
<Setter Property="Width" Value="120"></Setter>
<Setter Property="FontFamily" Value="Arial"></Setter>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="12"></Setter>
<Setter Property="Width" Value="120"></Setter>
<Setter Property="Height" Value="25"></Setter>
<Setter Property="Background" Value="Black"></Setter>
</Style>
<!-- .... and so on .... -->
</ResourceDictionary>
I am using this resource in the following window:
<Window x:Class="SiteSetupWindow4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:primatives="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework"
Title="A Screen">
<Window.Resources>
<ResourceDictionary x:Key="defaultStyleX">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary x:Name="DefaultStyles" Source="Resources/myStyle.xaml" />
<ResourceDictionary x:Name="Templates" Source="Resources/myTemplates.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
Now, I have another Resource Dictionary that contains DataTemplates that I am using within my window. It is called "myTemplates". The style is applied to the DataTemplate as expected; however, I would like to overwrite some aspects of the style within the DataTemplate (Like width for example).
This is what I have tired, however I cannot get the BasedOn property to work...
(myTemplate.xaml)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate x:Key="PanelInfo">
<StackPanel>
<StackPanel.Resources>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Width" Value="120" />
</Style>
<Style TargetType="Label">
<Setter Property="Width" Value="180" />
</Style>
<Style TargetType="ComboBox">
<Setter Property="Width" Value="120" />
</Style>
<StackPanel.Resources>
<StackPanel Orientation="Horizontal">
<Label Content="Type:"></Label>
<ComboBox>
<ComboBoxItem Content="{Binding Path=Type}" IsSelected="True"></ComboBoxItem>
</ComboBox>
<!--...and so on -->
</StackPanel>
</StackPanel>
</ResourceDictionary>
This fails....I have also tried using DynamicResource, but this also fails.
I'm not sure how to get around this.
Any advise would be greatly appreciated!
Thanks,
-Frinny
I was having the same problem with an extended Button Style.
The ResourceKey= is what solved it for me.
This worked:
<Style x:Name="ButtonVisibility"
TargetType="{x:Type Button}"
BasedOn="{StaticResource ResourceKey={x:Type Button}}">
The way you have BasedOn for a type is correct. This will work in theory as long as, at run time, the style that you are basing it on is merged into the tree correctly. Make sure you have the "myStyles.xaml" merged in correctly. You can check this by removing your style you tried to modify and make sure it displays correctly from your style in "myStyles.xaml."
If it isn't there are a lot of places you can go wrong, but it always helps to try merging the styles in the file you are working on, then work up the tree to see where it's missing.
This utility will help you look at what is happing in the tree at run time.
http://blois.us/Snoop/

WPF datagrid styling

I want to style a WPF datagrid and it seems to be really easy . As far as I understand I have to have code such as the following:
<Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type Custom:DataGridColumnHeader}" >
<Setter Property="Background" Value="#88800080" />
<Setter Property="Foreground" Value="White" />
</Style>
But my question is ..where do I place this code and how do I let the datagrid know to use the style above ?
Regards,
S
Put it in the resource of the xaml (local or global). The easiest is to put it in the local resource of the current xaml file:
<Page Name="SomeName"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type Custom:DataGridColumnHeader}" >
<Setter Property="Background" Value="#88800080" />
<Setter Property="Foreground" Value="White" />
</Style>
</Page.Resources>
<!-- The rest of the xaml -->
</Page>
The best place to put styles is in a resource dictionary, referenced in App.xaml.
Resource dictionary ("StyleResources.xaml" in this example):
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="TextBlockRightAlign" TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<Style x:Key="TextBlockTitle" TargetType="TextBlock">
<Setter Property="FontSize" Value="20" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
</ResourceDictionary>
Referencing the style dictionary in App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="StyleResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<ValueConverters:PriceConverter x:Key="PriceConverter"/>
</ResourceDictionary>
</Application.Resources>
Using the definition in a datagrid (column formatting here, but should work for headers as well):
<data:DataGridTextColumn Header="Charge" Width="100"
Binding="{Binding Charge, Mode=TwoWay, Converter={StaticResource PriceConverter}}"
ElementStyle="{StaticResource TextBlockRightAlign}" />
Note that the element inside the cell is a TextBlock, so you can use a style with a target type of TextBlock.
As for the "Type DataGridColumnHeader was not found": you need a second xml namespace entry since the DataGridColumnHeader is in the System.Windows.Controls.Primitives namespace. You need something like
xmlns:dg="clr-namespace:Microsoft.Windows.Controls.Primitives;assembly=WPFToolkit"
and then reference the new namespace in your style, e.g.
<Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type dg:DataGridColumnHeader}" >
Styles usually go:
<UserControl.Resources>
<Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type Custom:DataGridColumnHeader}" >
<Setter Property="Background" Value="#88800080" />
<Setter Property="Foreground" Value="White" />
</Style>
</UserControl.Resources>
Use the appropriate container if this isn't within a UserControl you may use "Window" or whatever container you're in.
Also you need to reference it in your datagrid with:
<Custom:DataGrid ColumnHeaderStyle="{StaticResource DataGridColumnHeaderStyle}"/>

Resources