WPF Opacity in a general style - wpf

I have this style that works as expected. I'm trying to generalize it for all controls.
Issue: if I replace the type ComboBox with Control. It does not work anymore.
I'm trying to avoid creating a style for each type of control.
<Style TargetType="{x:Type ComboBox}">
<Setter Property="IsEnabled" Value="{Binding Path=myProperty}"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="ComboBox.Opacity" Value="1" />
</Trigger>
</Style.Triggers>
</Style>

I don't think there's a way to do exactly what you want. While this won't allow you to avoid defining styles for each type it does cut down on the duplicated code by using BasedOn to inherit the style you define once:
<Resources>
<Style x:Key="InvisibleWhenDisabled" TargetType="{x:Type Control}">
<Setter Property="IsEnabled" Value="{Binding Path=myProperty}"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="ComboBox" BasedOn="{StaticResource InvisibleWhenDisabled}"/>
<Style TargetType="Button" BasedOn="{StaticResource InvisibleWhenDisabled}"/>
</Resources>

Related

Make text bold when mouse hovers over Context menu

I am wondering how to change the text when the mouse hovers over text in a context menu? I want the text to become Bold but not sure how to do this. Any help would be appreciated :). This is my resource style for the menu Items containing an image, which is where I think I should put it
XAML
<Style x:Key="MenuItemIcon" TargetType="MenuItem">
<Style.Resources>
<Style TargetType="ContentPresenter">
<Style.Triggers>
<Trigger Property="ContentSource" Value="Icon">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
You can try following :
<Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}" x:Shared="False">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
Let me know if it works for you :)
Regards,
To answer your another question, to change hover background please use the following :
<Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}" x:Shared="False">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Red" />
</Trigger>
</Style.Triggers>

How to inherit custom Textblock style in wpf datagrid?

I have TextBlock in the DataGridTemplateColumn in WPF Datagrid. when I check "IsEnable" false to inherit the Textblock Style inside the DatagridTemplateColumn. Here is XAML code i'm using:
<Style TargetType="{x:Type DataGrid}" >
<Setter Property="Template" >
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGrid }">
<ControlTemplate.Resources >
<Style TargetType="{x:Type TextBlock }">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</Style.Triggers>
</Style>
</ControlTemplate.Resources>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This did not work and later i tried:
<Style TargetType="TextBlock" >
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
Any Thoughts on how to check if the Texblock inside the Datagrid "IsEnabled" and inherit the Style?.
WPF does not apply implicit styles inside templates unless the TargetType derives from Control. Since TextBlock doesn't derive from Control, its style is not applied. So you either have to manually apply the style to every non-Control or define the implicit style inside the template.
Define your styles inside datagrid resources as
<DataGrid.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
I'm going to assume you are trying to toggle the foreground color based on the IsEnabled state of the TextBlock.
Where are you setting the IsEnabled = true Foreground color? You have not given the code for the actual TextBlock you are going to style.
Try this:
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
If this doesn't work, it means wherever your Textblock is defined, you are doing this -
<TextBlock .... Foreground="SomeColor" />
and you need to remove the Foreground setting directly on the TextBlock so that the Foreground color can be set by the style.

Sharing control templates between different button types

I want to define a style for ButtonBase and then extend that style in different ways for Togglebutton and Button. I want something like this:
<!-- Base Style -->
<Style x:Key="ButtonBaseStyle" TargetType="ButtonBase">
<Style.Resources>
<ControlTemplate x:Key="NormalStyle" TargetType="ButtonBase">...</ControlTemplate>
<ControlTemplate x:Key="HoverStyle" TargetType="ButtonBase">...</ControlTemplate>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Template" Value="{StaticResource HoverStyle}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Template" Value="{StaticResource NormalStyle}" />
</Trigger>
</Style.Triggers>
</Style>
<!-- Toggle Button -->
<Style x:Key="ToggleButtonStyle" TargetType="ToggleButton" BasedOn="ButtonBaseStyle">
<Style.Resources>
<ControlTemplate x:Key="CheckedStyle" TargetType="ToggleButton">...</ControlTemplate>
</Style.Resources>
<Style.Triggers>
<!-- ToggleButton should inherit the triggers defined in ButtonBaseStyle; adding the additional trigger specific to ToggleButton here -->
<Trigger Property="IsChecked" Value="True">
<Setter Property="Template" Value="{StaticResource CheckedStyle}" />
</Trigger>
</Style.Triggers>
</Style>
The style declaration for ToggleButton is wrong. WPF does not allow styles to inherit like that. I want to know if I can achieve this effect in any other way. Note that I am aware that I can make the control templates global and use them selectively for different button classes. That is what I am doing now but I would like to avoid that.
Actually the proposed way works, you just have one syntax error.
Replace:
BasedOn="ButtonBaseStyle"
With:
BasedOn="{StaticResource ButtonBaseStyle}"

How to apply a style from a resource dictionary if the Tag property is set

I have a style in a resource dictionary as so
<Style x:Key="heading" TargetType="Label">
<Setter Property="FontSize" Value="26" />
</Style>
and I wish to have it assigned to control if some trigger
condition is met. For example
<Style TargetType="Label">
<Style.Triggers>
<Trigger Property="Tag" Value="header" >
<Setter Property="FontSize" Value="26" />
</Trigger>
</Style.Triggers>
</Style>
works fine
<Style TargetType="Label">
<Style.Triggers>
<Trigger Property="Tag" Value="header" >
<Setter Property="Style" Value="{StaticResource heading}" />
</Trigger>
</Style.Triggers>
</Style>
gives an error that a Style trigger cannot change the Style property of the
associated target which sort of makes sense but is there a work around
for this?
The trick is to put the triggers into the resource dictionary not the Style like so
<Style TargetType="Label">
<Style.Triggers>
<StaticResource ResourceKey="headerTrigger"/>
</Style.Triggers>
</Style>
and define the trigger in a resource dictionary like so
<Trigger x:Key="headerTrigger" Property="Label.Tag" Value="header" >
<Setter Property="Label.FontWeight" Value="Bold"/>
<Setter Property="Label.BorderBrush" Value="Red"/>
<Setter Property="Label.BorderThickness" Value="2"/>
</Trigger>

wpf: add style to ComboBoxItem trough binding

I've a ComboBox and a Style for the items. The style is defined by using Style.Triggers in this way:
<Style>
<Style.Triggers>
<Trigger Property="Tag" Value="false">
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="Foreground" Value="BlueViolet"/>
</Trigger>
<Trigger Property="Tag" Value="true">
<Setter Property="Background" Value="LightGreen"/>
<Setter Property="Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
In order to embed this Style I would write next :
<ComboBox>
<ComboBoxItem Content="xxxx" Tag="true"/>
<ComboBoxItem Content="yyyy" Tag="false"/>
</ComboBox>
but how I can embed this Style in case I use DataContext binding?
Thanks in advance.
You could try adding a style setter to the ComboBox's Resources:
<ComboBox.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Tag" Value="{Binding SomeValue}" />
</Style>
</ComboBox.Resources>

Resources