Global Style not working in WPF [duplicate] - c#

This question already has answers here:
WPF Some styles not applied on DataTemplate controls
(4 answers)
Closed 8 years ago.
Why ist this Style not working in WPF? The TextBlock should be red, but it is not. It stays black. This is just happing when the TextBlock is in a Template.
<Window x:Class="WpfApplication2.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>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"></Setter>
</Style>
</Window.Resources>
<Grid>
<ListView>
<ListView.Items>
<ListItem></ListItem>
</ListView.Items>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock>Hallo</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>

Implicit Styles in templates are limited to controls that inherit from System.Windows.Controls.Control unless they are defined in Application.Resources so either give your style x:Key and use it explicitly:
<Window.Resources>
<Style TargetType="TextBlock" x:Key="myTextBlockStyle">
<Setter Property="Foreground" Value="Red"></Setter>
</Style>
</Window.Resources>
<TextBlock Style="{StaticResource myTextBlockStyle}">Hallo</TextBlock>
or move it to Application.Resources
<Application.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"></Setter>
</Style>
</Application.Resources>

If you want to define a style and have it automatically apply to all controls of that type (without manually specifying the style for each control) you need to define it like this instead.
E.G.
<Style x:Key="{x:Type TextBox}" TargetType="TextBox">
<Setter Property="IsUndoEnabled" Value="True"></Setter>
<Setter Property="UndoLimit" Value="10"></Setter>
<Setter Property="ContextMenu" Value="{StaticResource textContextMenu}"></Setter>
<Setter Property="SpellCheck.IsEnabled" Value="True"></Setter>
</Style>

Related

Style template for addin in WPF

I am designing a revit addin.I'm using WPF and I want to design style templates which can then be inherited by all WPF pages.I have read that I need to put the styles in app.xaml but there is no app.xaml as this is an addin.
As of now,I'm creating style templates but one template can only be used by the elements of that particular page.
I want to create a style template which every page can inherit without app.xaml.How do I do that?
If all you need is to share styles and maybe some resources you can do it without an App.xaml. In your project, create a xaml file to contain the shared styles and call it something like "MyCommonResources.xaml". It should simply contain a resource dictionary that holds the shared styles/resources. For example:
<ResourceDictionary 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"
xmlns:local="clr-namespace:MyAppNS">
<SolidColorBrush x:Key="Window.Background" Color="#FF202020"/>
<SolidColorBrush x:Key="MyTitleBar.Background" Color="#FF5A5A5A"/>
<SolidColorBrush x:Key="MyTitleBar.Foreground" Color="WhiteSmoke"/>
<SolidColorBrush x:Key="MyTitleBar.Disabled.Background" Color="Black"/>
<SolidColorBrush x:Key="MyTitleBar.Disabled.Foreground" Color="Gray"/>
<Style x:Key="CommandButtonStyle" TargetType="Button">
<Setter Property="MinHeight" Value="40"/>
</Style>
<Style x:Key="MyTitleBarStyle" TargetType="Label">
<Setter Property="Background" Value="{StaticResource MyTitleBar.Background}"/>
<Setter Property="Foreground" Value="{StaticResource MyTitleBar.Foreground}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="MinHeight" Value="34"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{StaticResource MyTitleBar.Disabled.Background}"/>
<Setter Property="Foreground" Value="{StaticResource MyTitleBar.Disabled.Foreground}"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
now in your xaml for the Window/Page/UserControl add a resource section and merge this dictionary in with the local...
<Window x:Class="MyAppNS.MyWPFWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyAppNS"
mc:Ignorable="d">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyCommonResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="MyLocalStyle" TargetType="Button">
<Setter Property="VerticalContentAlignment" Value="Left"/>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="This is the Title"
Style="{StaticResource MyTitleBarStyle}"/>
<Button x:Name="btnOK" Grid.Row="1" Content="OK"
Style="{StaticResource CommandButtonStyle}"
Click="btnOK_Click"/>
</Grid>
</Window>
Excuse me for any typos in the above, cut & pasted it from a Winforms app I have but quickly edited it down so it wouldn't be so large and changed some names to make better sense.
Do you have a WPF project or just a WPF view in a Forms application?
Maybe this contribution will help you ->
App.XAML where are you?

Get all elements that have texts

I have a application that already uses a style template to defining font family, font size, foregrounds colors and so on.
One funcionnality of that app is enable users to picker a particular color and then apply to all texts, including textblocks, listviews, buttons and etc.
I've already read this link (Find all controls in WPF Window by type), where I could find all objects' type of FrameworkElement and then apply the color to each element according with his type. However, I am not sure that is the best approach.
As you said, there are lots of way of doing this.
For starter, you can have a style template and then use StaticResource to get the style for it. For example:in your view mainwindow.xaml
<Window.Resources>
<Style TargetType="{x:Type Control}" x:Key="baseStyle">
<Setter Property="FontSize" Value="100" />
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource baseStyle}"></Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource baseStyle}"></Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource baseStyle}"></Style>
<Style TargetType="{x:Type ListView}" BasedOn="{StaticResource baseStyle}"></Style>
<!-- ComboBox, RadioButton, CheckBox, etc... -->
</Window.Resources>
OR Another way is:
View: mainwindow.xaml
<Window>
<Window.resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontSize"
Value="14" />
</Style>
</Window.resource>
<Grid>
<TextBox Text="blah"/>
</Grid>
</Window>
OR
you can do it from mainwindow constructor
Style = (Style)FindResource(typeof(Window));
and this, you will put this in the app.xaml
<Style TargetType="{x:Type Window}">
<Setter Property="FontSize"
Value="14" />
</Style>

How to apply different set of colors to each item in ItemsControl?

I have an ItemsControl and want each item to set its color theme based on data it contains. I have 2 resource dictionaries for 2 possible themes (Red and Blue) and a DataTemplate that defines how to apply those colors. How do I assign current resource dictionary for each row?
<Window x:Class="WpfApplication1.MainWindow"
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"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<!-- 2 dictionaries with style colors -->
<ResourceDictionary x:Key="RedStyle">
<SolidColorBrush x:Key="BorderBrush" Color="Red" />
<SolidColorBrush x:Key="TextBrush" Color="Red" />
</ResourceDictionary>
<ResourceDictionary x:Key="BlueStyle">
<SolidColorBrush x:Key="BorderBrush" Color="Blue" />
<SolidColorBrush x:Key="TextBrush" Color="Blue" />
</ResourceDictionary>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding list}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource BorderBrush}">
<TextBlock Text="{Binding}" Foreground="TextBrush" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
Update: The DataTemplate and brush sets are much larger in my real project. What I'm trying to do is to avoid duplicating DataTemplate layout code while still being able to have 2 different color styles on it.
Pertinent to your task, you can apply DataTriggers like shown in the following example:
<ItemsControl.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Items.TheAttribute}" Value="AttributeValue1">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="TextBrush" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding Items.TheAttribute}" Value="AttributeValue2">
<Setter Property="BorderBrush" Value="Blue"/>
<Setter Property="TextBrush" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.Style>
In this example, you do not need the Styles specified in your ResourceDictionary.
Alternatively, you can use <Style.Triggers> to set the Style per your ResourceDictionary rather than setting the values of individual properties.
Hope this may help.
Note : You cannot apply ResourceDictionary conditionally, using Triggers.
You have four options at your disposable.
Put your DataTemplate in single resource dictionary, or corresponding DataTemplates in separate dictionaries.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<DataTemplate DataType="{x:Type sys:String}">
<TextBlock Text="{Binding .}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="Text" Value="Name1">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ResourceDictionary>
Usage :
<ItemsControl.Resources>
<ResourceDictionary Source="RedStyle.xaml"/>
</ItemsControl.Resources>
Use DataTemplateSelector to apply some complicated logic and assign DataTemplates accordingly. There are good tutorials on net on this.
Use Blend Behaviors to do this using pure XAML.
Use Loaded event of the control present in DataTemplate to load Res Dictionary using code. Simplest approach !
<DataTemplate>
<TextBlock Loaded="TextBlock_Loaded" Text="{Binding .}"/>
</DataTemplate>
Code :
private void TextBlock_Loaded(object sender, RoutedEventArgs e)
{
TextBlock tb = sender as TextBlock;
if (tb.Text == "Name123")
tb.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("RedStyle.xaml", UriKind.Relative) });
}
There is an AlternationCount:
<ItemsControl ItemsSource="{Binding List}"
AlternationCount="2"
HorizontalContentAlignment="Stretch">
plus:
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="White" TargetName="Grid" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#FFF1F1F1" TargetName="Grid" />
</Trigger>
</DataTemplate.Triggers>

User control TextBlock.FontSize cannot be changed when style defined in App.xaml

I have a user control that doesn't have xaml part, it's completely written in C#, but the Control template is written in xaml using ResourceDictionary, this is mainly due the issue related to naming user controls (http://devdump.wordpress.com/2010/02/24/cannot-set-name-attribute-value-error/), so, Control Template is loaded dynamically in control's constructor.
This control is similar to TabControl, it has items and each item have Header and Content, thus the control template is used (to filter out the content and display only the header). It all works fine except that when I now add the style (FontSize) in App.xaml for TextBlock I cannot change the FontSize locally, I cannot change even the FontSize in the template it self, it is always using the one defined in app.xaml. If I remove the style from app.xaml, everything works fine.
My global style looks like (app.xaml):
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="14" />
<Setter Property="FontFamily" Value="Segoe UI" />
</Style>
My template is something like this:
<ControlTemplate x:Key="MyTemplate" TargetType="MyControl">
<StackPanel x:Name="mainStack" Background="Transparent">
<StackPanel Background="{TemplateBinding Background}" Orientation="Horizontal" TextBlock.Foreground="{TemplateBinding HeaderForeground}">
<Image Source="{TemplateBinding Source}" Margin="10, 0, 0, 0"/>
<ContentPresenter x:Name="contentPresenter" ContentSource="Header" Margin="{TemplateBinding Padding}"/>
</StackPanel>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{Binding Path=SelectedBackground, RelativeSource={RelativeSource Mode=Self}}" />
<Setter Property="Foreground" Value="{Binding Path=SelectedForeground, RelativeSource={RelativeSource Mode=Self}}" />
</Trigger>
<Trigger SourceName="mainStack" Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding Path=HoverBrush, RelativeSource={RelativeSource Mode=Self}}"/>
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
The code which I use to load the template from resource dictionary is:
ResourceDictionary dic = new ResourceDictionary();
dic.Source = new Uri("mynamespace", UriKind.RelativeOrAbsolute);
this.Template = (ControlTemplate)dic["MyTemplate"];
So, to summarize, changing the TextBlock.FontSize is not possible, global value is always used, it cannot be overridden even if setting it directly in template itself.
Here is an update on this issue:
If I have a UserControl which has TextBlock defined, and if I want to change it's properties via attached properties it won't have effect, global style will be still applied and any local settings will be ignored.
User control:
<UserControl x:Class="WpfApplication1.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock>Inside the user cotnrol TextBlock</TextBlock>
</Grid>
</UserControl>
Main window:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBlock FontSize="20" Text="Naked TextBlock"/>
<local:MyControl TextBlock.FontSize="20"/>
</StackPanel>
And same global style:
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
</Style>

Non-keyed styles in App.xaml do not get applied to user controls

In my C# / WPF / .NET 4.5 project, my App.xaml contains the following:
<Application x:Class="HsWpfApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style x:Key="h1" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="Segoe UI Light" />
<Setter Property="FontSize" Value="20pt" />
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<!-- ... -->
<Style TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="Segoe UI Symbol" />
<Setter Property="FontSize" Value="11pt" />
<Setter Property="Margin" Value="0,10"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="BorderBrush" Value="DarkGray"/>
</Style>
<!-- ... -->
</Application.Resources>
</Application>
I also have a user control, under the sub-namespace HsWpfApplication.Controls, defined in the following manner:
<UserControl x:Class="HsWpfApplication.Controls.Manager"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="300">
<UserControl.Resources>
<DataTemplate x:Key="ManagerItemDataTemplate">
<!-- ... -->
</DataTemplate>
</UserControl.Resources>
<Grid>
<!-- -->
<Grid Grid.Row="0">
<TextBlock Style="{StaticResource h1}" Margin="10,0,0,0" HorizontalAlignment="Left">Manager</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Command="{Binding CreateNewItemCollectionCommand}"
ToolTip="New Item Collection"
Margin="0,10,10,10"
Width="40" Height="40"
FontSize="18"
Content=""/>
<!-- ... -->
</StackPanel>
</Grid>
<!-- ... -->
</Grid>
</UserControl>
The keyed style h1 is applied to the TextBlock just fine. The non-keyed style that I want applied to the Buttons does not work:
How do I get non-keyed styles in my App.xaml file to affect my user controls?
Have you tried to add a very obvious value to your implicit style? I would suggest FontSize='48' or something like that. Perhaps the problem is that you don't have the 'Segoe UI Symbol' present on your system?

Categories