I have a Button and its Style:
<Button Name="MyBtn" Style="{StaticResource ButtonEnabledStyle}"
IsEnabled="False" Opacity="1" />
<Style x:Key="ButtonEnabledStyle" TargetType="Button">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True" >
<Setter Property="Opacity" Value="0.1" />
</Trigger>
</Style.Triggers>
</Style>
But when I enable the Button (MyBtn.IsEnabled = true) it does not change its Opacity. Why? How can I solve this problem? Thanks.
A local value set on the element (Opacity="1" in your code) will always take precedence over a style or style trigger value. Please have a look at Dependency Property Setting Precedence List.
An easy fix is to set the default value on the style instead:
<Style x:Key="ButtonEnabledStyle" TargetType="Button">
<Setter Property="Opacity" Value="1.0" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True" >
<Setter Property="Opacity" Value="0.1" />
</Trigger>
</Style.Triggers>
</Style>
Related
I'm trying to recreate a Valve VGUI interface style in WPF. So far I am able to assign a border to a button, but the border style does not change when pressing the button.
Here's my XAML code:
<Window.Resources>
<Style x:Key="BorderLight_Style" TargetType="Border">
<Setter Property="BorderBrush" Value="#889180" />
<Setter Property="BorderThickness" Value="1,1,0,0" />
</Style>
<Style x:Key="BorderShadow_Style" TargetType="Border">
<Setter Property="BorderBrush" Value="#FF282E22" />
<Setter Property="BorderThickness" Value="0,0,1,1" />
</Style>
<Style x:Key="BorderLight_Style_pressed" TargetType="Border">
<Setter Property="BorderBrush" Value="#FF282E22" />
<Setter Property="BorderThickness" Value="1,1,0,0" />
</Style>
<Style x:Key="BorderShadow_Style_pressed" TargetType="Border">
<Setter Property="BorderBrush" Value="#889180" />
<Setter Property="BorderThickness" Value="0,0,1,1" />
</Style>
<Style TargetType="Grid">
<Setter Property="Background" Value="#FF4C5844" />
</Style>
<Style TargetType="Button">
<Setter Property="Background" Value="#FF4C5844" />
<Setter Property="Foreground" Value="#D8DED3" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="border" Style="{StaticResource BorderShadow_Style}">
<Border x:Name="border2" Style="{StaticResource BorderLight_Style}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Style" Value="{StaticResource BorderShadow_Style_pressed}" />
<Setter TargetName="border2" Property="Style" Value="{StaticResource BorderLight_Style_pressed}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Am I doing anything wrong with this? Thanks!
Controls need to have a defined Background property to participate in hit-testing - and thus to allow the IsPressed property to be set on a Button for example.
Set the Background property of your inner Border to any valid value - such as Transparent - to fix your Trigger.
Note: if you were to press TAB to select your button and press the space bar, you would see your Trigger working even though you didn't set it any background, because IsPressed also reacts to the space bar.
Here is a simple XAML with trigger that should change ToggleButton content when it is checked. But for some reason it doesn't work. I have a silly feeling that I missed something extra small. Appreciate your help
<ToggleButton Content="<">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value=">" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
You must move Content="<" from ToggleButton to setter of Style.
Example:
<ToggleButton>
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Content" Value="<" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value=">" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
Because local value has higher precedence order over Style setters and triggers:
Property system coercion.
Active animations, or animations with a Hold behavior.
3. Local value.
TemplatedParent template properties.
Implicit style.
6. Style triggers.
Template triggers.
8. Style setters.
...
For more information, please see:
MSDN: Dependency Property Value Precedence
You are overriding the Content set by the Trigger by setting the Content attribute at the control level. You want to set it using a Setter within the Style instead:
<ToggleButton>
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Content" Value="<" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value=">" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
When i add this controltemplate my checkboxes disapear and only the checkbox text is shown. And when mouse is over the textbackground becomes red, how do i get my checkbox background red when mouse is over?
<Style TargetType="CheckBox" x:Key="Checkbox">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Margin" Value="20,15,0,0" />
<Setter Property="FontFamily" Value="/Resources/Fonts/Source Sans Pro/#Source Sans Pro" />
<Setter Property="FontSize" Value="14" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Foreground" Value="{DynamicResource CheckboxForegroundColor}" />
<Setter Property="Background" Value="{DynamicResource CheckboxBackgroundColor}" />
<Setter Property="BorderBrush" Value="{DynamicResource CheckboxBorderbrushColor}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<CheckBox Background="{TemplateBinding Background}" >
<ContentPresenter />
</CheckBox>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
This will work for some properties (try FontSize, for example), but not for others. The default template for the CheckBox has triggers of its own, and they don't bother with such things as TemplateBindings.
This post tells you how to extract the default template for a ComboBox. Here is an excerpt which shows your problem:
<ControlTemplate.Triggers>
...
<Trigger Property="IsMouseOver" Value="true">
<Setter
Property="Background"
TargetName="checkBoxBorder"
Value="{StaticResource OptionMark.MouseOver.Background}"/>
...
</Trigger>
...
</ControlTemplate.Triggers>
Your best bet is probably to override the entire template. Happily, it isn't too complex...
Remove your own template.
Follow the steps outlined in the post I linked to. That should give you a copy of the default CheckBox template.
Modify that copy. In particular, the IsMouseOver trigger that I excerpted: Change {StaticResource OptionMark.MouseOver.Background} to Red.
If this is still unclear, see this related post.
I have just started learning WPF and trying to hide a StackPanel during MouseOver. Below is the code that I use. I can only see the Panel flickering when mouse is placed on it but, it doesn't hide completely. Am I missing something here? Thanks in advance.
<Style x:Key="myStyle" TargetType="{x:Type StackPanel}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsMouseOver" Value="false">
<Setter Property="Visibility" Value="Visible" />
</Trigger>
</Style.Triggers>
</Style>
Stackpanel:
<StackPanel Style="{StaticResource myStyle}">
// Child controls
</StackPanel>
When the StackPanel is hidden, the IsMouseOver property toggles to false, which makes the StackPanel visible again.
You might set the Opacity property instead of Visibility:
<Style x:Key="myStyle" TargetType="{x:Type StackPanel}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Opacity" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
Or, as pointed out in the other answer, declare just one Trigger for IsMouseOver == true:
<Style x:Key="myStyle" TargetType="{x:Type StackPanel}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0" />
</Trigger>
</Style.Triggers>
</Style>
Clemens has already answered your question, but just FYI when you are triggering on a Boolean value, you don't need a trigger for both states. Just set a single trigger for the true or false state, then when the state no longer applies the properties that were changed by the setters in the trigger will revert back to their previous values. This will cut down on the amount of XAML you need to write.
I'd like to get rid of the grey-fading out behavior of datagrid cells (Checkboxes, Timepicker, comboboxes etc) when they have been set to disabled.
So this is what I'm trying to do:
<Style TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{x:Null}" />
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
But it doesn't work.
Do I need to define the styles individually for the controls that's actually inside the datagridcell (Checkboxes, comboboxes etc)? What's a good way of making this work?
Firstly, the fact is that the property IsEnabled hard-coded in certain control, so setting properties such as Background impossible, because the color hardcoded in the control. For example - Background in: ComboBox, TextBox, etc. Therefore, in such cases, create styles and templates, overriding the default behavior of the control (in our case: IsEnabled=False behavior).
Secondly, what control in the assigned property DataTemplate IsEnabled like this:
<DataGridTemplateColumn x:Name="ComboBoxColumn" Header="ComboBox Header" Width="110">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox IsEnabled="False" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Not to say that DataGridCell will be False, therefore, the trigger will not fire:
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Black" />
</Trigger>
</Style.Triggers>
Hence the conclusion:
Determine the behavior of the control when it is enabled false. Styles for each control can be taken from MSDN.
Example style for CheckBox (link):
<Style x:Key="{x:Type CheckBox}" TargetType="CheckBox">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource CheckBoxFocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Border x:Name="Border" Width="13" Height="13" CornerRadius="0" Background="{StaticResource NormalBrush}" BorderThickness="1" BorderBrush="{StaticResource NormalBorderBrush}">
<Path Width="7" Height="7" x:Name="CheckMark" SnapsToDevicePixels="False" Stroke="{StaticResource GlyphBrush}" StrokeThickness="2" Data="M 0 0 L 7 7 M 0 7 L 7 0" />
</Border>
</BulletDecorator.Bullet>
<ContentPresenter Margin="4,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" RecognizesAccessKey="True" />
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="false">
<Setter TargetName="CheckMark" Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter TargetName="CheckMark" Property="Data" Value="M 0 7 L 7 0" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource DarkBrush}" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource PressedBrush}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource PressedBorderBrush}" />
</Trigger>
<!-- Here set the some properties there IsEnabled will be false -->
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="Red" />
<Setter TargetName="Border" Property="BorderBrush" Value="Green" />
<Setter Property="Foreground" Value="Orange"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have defined the attached DependencyProperty for a column that shows whether it is turned off. Thereafter, each control in the template column is referenced like that:
<DataGridTemplateColumn x:Name="CheckBoxColumn" local:MyDependencyClass.IsEnabledColumn="False" Width="110" Header="CheckBox Header">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Content="My CheckBox" IsEnabled="{Binding Source={x:Reference Name=CheckBoxColumn}, Path=(local:MyDependencyClass.IsEnabledColumn)}" IsChecked="False" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Set the property IsEnabledColumn, you can set for those controls that you want to disable (IsEnabled=False).
Listing of MyDependencyClass:
public class MyDependencyClass : DependencyObject
{
public static readonly DependencyProperty IsEnabledColumnProperty;
public static void SetIsEnabledColumn(DependencyObject DepObject, bool value)
{
DepObject.SetValue(IsEnabledColumnProperty, value);
}
public static bool GetIsEnabledColumn(DependencyObject DepObject)
{
return (bool)DepObject.GetValue(IsEnabledColumnProperty);
}
static MyDependencyClass()
{
PropertyMetadata MyPropertyMetadata = new PropertyMetadata(false);
IsEnabledColumnProperty = DependencyProperty.RegisterAttached("IsEnabledColumn",
typeof(bool),
typeof(MyDependencyClass),
MyPropertyMetadata);
}
}
P.S. Don't worry about {x:Reference} warning message, it can be ignored.