Can't use button property in trigger in WPF - wpf

I have button with custom content (a red circle) defined inside a user control and I want the circle to change to gray if the button is disabled.
I tried the following and it does not compile
Error: 'IsEnabled' member is not valid because it does not have a qualifying type name.
Can any explain what I am doing wrong here?
<Button>
<Button.Content>
<Grid>
<Ellipse x:Name="circle" Width="20" Height="20" Fill="Red"/>
</Grid>
</Button.Content>
<Button.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="circle" Property="Fill" Value="Gray"/>
</Trigger>
</Button.Triggers>
</Button>

IsEnabled is a DependecyProperty that's defined on a class that Button inherits from; XAML requires that you explicitly specify the owning type. Try Trigger Property="UIElement.IsEnabled" instead.

Here's a way to do it:
<Button Name="btn" >
<Ellipse Height="20" Width="20">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Fill" Value="Red" />
<!-- Here is the 'normal' content -->
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled, ElementName=btn}" Value="False">
<Setter Property="Fill" Value="Blue" />
<!-- Here is the 'override' content -->
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</Button>
DataTriggers only work in styles, so we needed to target the actual element that was receiving the style but bind to another element in the control.

Related

How to change the orientation property of WrapPanel by trigger?

I want to know how to change the WrapPanel orientation property by triggers.
I use trigger to change the wrap panel orientation property, but it doesn't work.
<WrapPanel Orientation="Horizontal">
<WrapPanel.Style>
<Style TargetType="WrapPanel">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="Red"/>
<Setter Property="Orientation" Value="Vertical"/>
</Trigger>
</Style.Triggers>
</Style>
</WrapPanel.Style>
<Button Content="button1" Margin="10"/>
<Button Content="button2" Margin="10"/>
</WrapPanel>
I expect the button to be Vertical and the background to be Red, but the result is Horizontal button and Red background. Background is changed right, but orientation is not changed.
set default Orientation value via Style Setter. Orientation="Horizontal" is a local value, which cannot be reset by Style Trigger
<WrapPanel>
<WrapPanel.Style>
<Style TargetType="WrapPanel">
<Setter Property="Orientation" Value="Horizontal"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="Red"/>
<Setter Property="Orientation" Value="Vertical"/>
</Trigger>
</Style.Triggers>
</Style>
</WrapPanel.Style>
<Button Content="button1" Margin="10"/>
<Button Content="button2" Margin="10"/>
</WrapPanel>

Is there a MouseDown setter property for a rectangle that acts as a button control template?

As the title suggests, I'm looking for a trigger property that triggers when the left mouse button is clicked over the button. Problem being my button has a rectangle as it's control template and I'd like to change the fill/stroke when the button/rectangle is clicked.
The only trigger property I can find that works is "IsMouseOver"
Anything like MouseDown or IsPressed doesn't work.
My xaml right now:
<Button x:Name="my_Button" Click="my_Button_Click" Margin="268,91,-266,-94">
<Button.Template>
<ControlTemplate>
<Rectangle HorizontalAlignment="Left" Height="20" Stroke="Black" VerticalAlignment="Top" Width="141" Margin="105,10,0,0" StrokeThickness="2">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Blue" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" Value="Red"/>
<Setter Property="Stroke" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</ControlTemplate>
</Button.Template>
</Button>
Where the Trigger Property "IsMouseOver" is I would like the property to be MouseDown, and then proceeding to set the fill and stroke of the rectangle to different colors.
xaml I've tried that hasn't worked:
<Trigger Property="MouseDown" Value="True">
<Setter Property="Fill" Value="Red"/>
<Setter Property="Stroke" Value="Black"/>
</Trigger>
Edit: I would like to clarify that IsMouseOver works perfectly with the trigger property, but I need it to be when the mouse is clicked on the button rather than hovered over.
See the DataTrigger below :
<Button x:Name="my_Button" Click="my_Button_Click" Margin="268,91,-266,-94">
<Button.Template>
<ControlTemplate>
<Rectangle HorizontalAlignment="Left" Height="20" Stroke="Black" VerticalAlignment="Top" Width="141" Margin="105,10,0,0" StrokeThickness="2">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Blue" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True">
<Setter Property="Fill" Value="Red"/>
<Setter Property="Stroke" Value="Black"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</ControlTemplate>
</Button.Template>
</Button>

Change style of a child control on MouseOver in WPF

I have a custom control that holds two Rectangles and several TextBoxes. I wish to change the background color of the Rectangle on MouseOver.
I add trigger as following:
<Rectangle
Grid.Column="1"
Fill="#FF383838"
Grid.ColumnSpan="3"
Margin="0,4,4,4">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="#FF383838" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" Value="#FF575757" />
</Trigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
But since rectangle is part of my control, I assume the event is not firing.
Setting a property via XAML will be applied over the style properties that you try to set. To fix this, remove Fill=#FF383838 so you should have:
<Rectangle Grid.Column="1"
Grid.ColumnSpan="3"
Margin="0,4,4,4">
//... rest of code here
Try this code:
<Window.Resources>
<Style TargetType="Rectangle" x:Key="test">
<Setter Property="Fill" Value="#FF383838" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" Value="#FF575757" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Rectangle Style="{StaticResource test}" />

How to set Panel.ZIndex or other attached properties via DataTrigger?

I am trying to have a circular overlay come to the top when a certain view model enters an offline state. So it becomes partially transparent and on top of other elements in the Grid.
DataTriggers in the style have worked for everything so far, but I cannot set Panel.ZIndex. There is no error in build or run, but the property is not set (I assume because it's an attached property?)
<Ellipse Fill="DarkGray" Panel.ZIndex="-10" Width="50" Height="50">
<Ellipse.Style TargetType="Ellipse">
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="Offline">
<Setter Property="Opacity" Value=".6" />
<Setter Property="Panel.ZIndex" Value="10" />
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
You have the syntax correct, however the problem is that you are defining Panel.ZIndex in the <Ellipse> tag, and properties set in the tag itself will take precedence over any triggered values.
To fix it, simply set Panel.ZIndex in your style instead of the Ellipse tag
<Ellipse Fill="DarkGray" Width="50" Height="50">
<Ellipse.Style TargetType="Ellipse">
<Style>
<Setter Property="Panel.ZIndex" Value="-10" />
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="Offline">
<Setter Property="Opacity" Value=".6" />
<Setter Property="Panel.ZIndex" Value="10" />
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
See MSDN's article on Dependency Property Precedence for more info

Use a property trigger to change a property that already has a binding

How can I use a property trigger in a style (or another method) to change a property (ToolTip for example) that already has its value defined by a binding?
I have a simple button like so:
<Button Name="Button1" Style="{StaticResource ButtonStyle}"
ToolTip="{Binding Name}" >My Button</Button>
It has a binding on the tooltip to show the Name property of the class set as DataContext.
My problem is I want to show the Name when the button is enabled, but something else when it is disabled. I thought I could get around my problem with a style and a trigger like so:
<Style TargetType="Button" x:Key="ButtonStyle">
<Setter Property="ToolTipService.ShowOnDisabled" Value="True" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="ToolTip" Value="Disabled" />
</Trigger>
</Style.Triggers>
</Style>
But this doesn't work. If I removed the tooltip binding from the button then I do get the correct tooltip when the button is disabled. But it seems I can't have both a binding and a trigger on the same property.
I could get around it by adding another trigger like so:
<Trigger Property="IsEnabled" Value="true">
<Setter Property="ToolTip" Value="{Binding Name}" />
</Trigger>
But I would like to use the style for 4 or 5 buttons that will all have different bindings for the enabled ToolTip, but the same (fixed) tooltip when they are disabled.
Any suggestions?
The easiest solution to your problem is to create a button style that all of your buttons can use (_DisabledButtonToolTipStyle in the example below) and then define a unique style for each button that applies the enabled tool tip value. If the individual buttons always have a different tool tip value then I'd recommended simply embedding the style like below; however, if you wanted to reuse the enabled tool tip style you could easily define it in your resources and give it a key.
<Window.Resources>
<Style x:Key="_DisabledButtonToolTipStyle" TargetType="Button">
<Setter Property="ToolTipService.ShowOnDisabled" Value="True" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="ToolTip" Value="Disabled" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button Name="Button1" Content="My Button">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource _DisabledButtonToolTipStyle}">
<Setter Property="ToolTip" Value="{Binding Name}" />
</Style>
</Button.Style>
</Button>
</Grid>
Your problem has nothing to do with binding, the problem is that properties you set directly on the element override the properties set in a style, for example:
Given the style
<Style TargetType="Button">
<Setter Property="Background" Value="Blue"/>
</Style>
And those two buttons:
<Button Content="1st"/>
<Button Content="2nd" Background="Red"/>
The first button will get its background from the style but the second overrides the style background.
You can get what you want with triggers but not using styles, you can use a DataTemplate like this (the TextBox and CheckBox are there for testing):
<ContentPresenter Content="{Binding}">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<StackPanel>
<TextBox Name="edt" Text="Tooltip text"/>
<Button Name="btn" Content="x"
ToolTip="{Binding ElementName=edt, Path=Text}"
ToolTipService.ShowOnDisabled="True"/>
<CheckBox Content="Enabled"
IsChecked="{Binding ElementName=btn, Path=IsEnabled}"/>
</StackPanel>
<DataTemplate.Triggers>
<Trigger SourceName="btn" Property="IsEnabled" Value="False">
<Setter TargetName="btn" Property="ToolTip" Value="Disabled"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>

Resources