So I am trying to create button style (background opacity to black with 20% alpha and default colour of text changes to clear white) with using ResourceDictionary. I do include file into App.xaml like:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Style/ButtonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
and to button I am applying x:Key, Style="{StaticResource TopBarButtons}"
So my style of it looks like (random colours just to test):
<Style x:Key="TopBarButtons" TargetType="{x:Type Button}">
<Setter Property="Background" Value="HotPink"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" Background="{TemplateBinding Background}" BorderThickness="1" Padding="5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="Background" Value="Lime" />
</Trigger>
</Style.Triggers>
</Style>
But none of those are detecting, nothing change at all.. What's my error?
Setting
<Button ... Background="Transparent"/>
directly on the Button sets a so-called local value, which takes higher precedence than a value set by a Style Setter or a Setter in a Style Trigger.
Any value that should be changed by a Style Trigger can only be initialized by a Style Setter, e.g.
<Setter Property="Background" Value="Transparent"/>
For reference, see Dependency property value precedence.
Related
My first steps in WPF and C# and i don't get it to work... :(
I have an application with two grids inside one window. I have to change the style of the first grid, so i started reading and reached using ControlTemplate.
My Grid now looks as i wanted it. But i only want that the first grid looks this way. the second one on the same page should have another style.
Is it possible to bind the controltemplate only on one grid. Maybe by name or soemthing identifying?
My ControlTemplate Code for now i have written in window.resources looks:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
Margin="0,0,0,0"
Background="Black"
BorderBrush="Black"
BorderThickness="0,2,0,0"
CornerRadius="0,0,0,0" >
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="0,0,0,20"
RecognizesAccessKey="True"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="#FF454E54" />
<Setter TargetName="Border" Property="Background" Value="#FF0A3651" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="White" />
<Setter TargetName="Border" Property="Background" Value="#FF454E54" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You could give the Style or ControlTemplate an x:Key ( <Style x:Key="key" TargetType="{x:Type TabItem}"> ) and apply it to the element you want by setting the element's Style or Template property like this:
<TabItem Style="{StaticResource key}">
A Style without an x:Key is implicit and will be applied to all elements whose type matches the specified TargetType of the Style.
Instead of writing your template under Window.Resources do it under your Grid.Resources
Try this. All this is doing is setting the style of the TabItem directly.
<TabItem> <!-- This is your TabItem control -->
<TabItem.Style>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<!-- ControlTemplate here -->
</Controltemplate
</Setter.Value>
</Setter>
</Style>
</TabItem.Style>
</TabItem>
I have a global style (Application.Resources) to set the Foreground of all TextBlocks.
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Brown"/>
</Style>
This works fine.
Now I try to override the Foreground of the TextBlock inside of a selected ListBoxItem, which is part of default ContentPresenter content.
I created a new global style for the ListBoxItem:
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="Orange" />
<Setter Property="Background" Value="Aqua"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Brown" />
<Setter Property="Foreground" Value="Aqua" />
</Trigger>
</Style.Triggers>
</Style>
The background works fine.
But Foreground has still the brush form de global style from the TextBlock.
Which is the best way to set the Foreground in a solution that works with Binding?
This is an example of why defining an implicit application-wide TextBlock style is usually a bad idea.
But you should be able to override it by adding a default style to to <ContentPresenter.Resources>:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Background="{TemplateBinding Background}">
<ContentPresenter>
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}" BasedOn="{x:Null}" />
</ContentPresenter.Resources>
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
Static Resource Style
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Red"></Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
Toggle Button Code
<ToggleButton Grid.Row="3" Grid.Column="1" ToolTip="Toggle to Show and Hide Date" IsChecked="True" Cursor="Hand">
<ToggleButton.Style>
<Style TargetType="{StaticResource ToggleButton}">
<Setter Property="Content" Value="No Date" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="Date" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
But I'm unable to set the content getting error as Content is not recognized or inaccessible.
I'm not a frequent user of WPF.
Thanks
In your Toggle Button Code, Change
<Style TargetType="{StaticResource ToggleButton}">
to
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Type ToggleButton}}">
You can have a style defined for a control globally that is/may apply to all controls of that type, but when you have to give individual control some extra styling you can do that by creating a style within the control and base that style on the global style.
This basedOn can be done on style x:Type (as in my answer), or can be based on x:Name as well if you want to base it on a specific style.
I just started getting used to WPF using Blend for Visual Studio. I created previous programs with the standart Windows Forms and now want to get to something more modern.
But I already encountered a main problem after like 5 Minutes.
I added a button with an background image with a transperancy. That worked like a charm, but the problem is that, when I run the application, the button always gets blue when the Mouse hovers it. I do not want this blue effect but can't find the option to disable it in Blend.
Hope someone can help me with this stupid question, Windows Forms was a little
What you're describing is the default state behavior for the button. You would have to create a custom template or style to change it. Example:
<Button Content="Button">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I am demonstrating two properties changes here: Background & Foreground. You may have as many as you want and change them to whatever value you wish. If you don't want any changes, simply remove Style.Triggers or a particular property within it.
Here's a demo for you, since you're new:
Here's the Resource Dictionary way:
Create a Resource Dictionary and add a style to it:
<Style x:Key="CustomButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
Place this in your App.xaml or wherever you merge your resource dictionaries:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ButtonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Then simply specify the style for your button:
Style="{StaticResource CustomButtonStyle}"
Here is the XAML in my application resources that globally changes all of the Button controls in the application to look and behave like I want:
<Style TargetType="{x:Type Button}" x:Key="MyButtonStyle">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" CornerRadius="0" BorderThickness="0"
Background="CornflowerBlue" BorderBrush="CornflowerBlue">
<ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True" />
</Border>
<ControlTemplate.Triggers>
<!-- a bunch o' triggers here -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
On one of my application's user controls, I would like to change some properties of this button. Here is some XAML that I am using in the UserControl.Resources section now to do this:
<Style x:Key="SpecialButton" TargetType="Button" BasedOn="{StaticResource MyButtonStyle}">
<Setter Property="Width" Value="20" />
<Setter Property="Visibility" Value="Collapsed" />
<Setter Property="Content" Value=">" />
<Setter Property="Border" Value="#eeeeee" />
<Setter Property="Border.Background" Value="#eeeeee" />
</Style>
The Button controls on my UserControl that I assign the style to of SpecialButton have the correct width, visibility, and content, but these last two attempts do not work. How would I go about changing the background color of the Border with a name of "Border" from the application resource in this SpecialButton style?
What you can do is use TemplateBinding to set the Background property on the control, in the base style. Also in the base style, set the Background color to the default "CornflowerBlue".
<Setter Property="Background" Value="CornflowerBlue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" Background="{TemplateBinding Background}"
Now you can overwrite the Background in the derived style:
<Style x:Key="SpecialButton" TargetType="Button" BasedOn="{StaticResource MyButtonStyle}">
<Setter Property="Background" Value="#eeeeee" />
(Note that, if you want to use other properties that aren't defined on the Button control -- or, say you wanted to use multiple background colors -- then you'd have to create your own control that inherits Button, and expose the new properties as Dependency Properties.)