WPF Inline style not setting template values - wpf

I have some base button styles that i want to inheritand make some minor changes, but not in the main style.
I extracted the main problem to a new application with minimal xaml.
The only thing i want to accomplish is change the button height when the button is disabled.
The two triggers are what i have tried , neither seem to work or give any debug messages about unable to find what its binding to.
<Button HorizontalAlignment="Center"
Height="90"
Margin="5"
Click="Button_Click"
VerticalAlignment="Bottom">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="Button.IsEnabled"
Value="False">
<Setter Property="Button.Height"
Value="50" />
</Trigger>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}"
Value="False">
<Setter Property="Button.Height"
Value="50" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
Foo Bar
</Button>
The button click
private void Button_Click(object sender, RoutedEventArgs e)
{
(sender as FrameworkElement).IsEnabled = false;
}
Thanks for reading.

Both triggers do work. You set explicitly Height="90" and it overrides your style! If you want it works you should set the initial height in the style and delete it from Button tag.
<Style TargetType="Button">
<Setter Property="Button.Height" Value="90" />
<Style.Triggers>
<Trigger Property="Button.IsEnabled"
Value="False">
<Setter Property="Button.Height"
Value="50" />
</Trigger>
</Style.Triggers>
</Style>

Related

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}" />

Can't use button property in trigger in 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.

using a trigger to set a button IsEnabled to be true on mouse over

I am trying to set a button so only when a mouse is going over it the
button will change his visual properties to an enabled button.
This is my code:
<Button Foreground="Black" Content="OK" Margin="186,100,170,172" >
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="IsEnabled" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Thanks in advance for your help.
You could encapsulate your Button in a Border to get what you're after
<Border Name="buttonBorder" Margin="186,100,170,172"
Background="#01000000" BorderBrush="Transparent" BorderThickness="0">
<Button Foreground="Black" Content="OK">
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=buttonBorder, Path=IsMouseOver}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Border>
I don't think it's possible what you want to do here, because while the button is disabled, IsMouseOver is false (also, it doesn't generate MouseMove or other events).
To achieve what you want (btw, why would you want a disabled button to become enabled when you put the mouse over it? It's so unnatural... how about if you want to navigate with the keyboard to the button? it will be impossible if it is disabled), you should restyle the button and make it look as in its disabled state when the mouse is not over it and as in its enabled state when the mouse is over it - but this will require some work).

'Graying Out' a WPF button image?

I have a simple Button control that contains an Image object as its content. I want so set the Image opacity to 0.5 when the Button is disabled to provide an additional visual cue as to the Button status.
What is the simplest way to accomplish that result in XAML? Thanks for your help.
Use a trigger in the Image style. (It would be more natural to put it in the Button style, but the Button style can't easily affect the Image for annoying technical reasons. It could be done in the Button's ControlTemplate but that's overkill for what you want here.)
<Button>
<Image Source="something.png">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
Note we are taking advantage here of the fact that the Image will be disabled when the Button is disabled, so we can trigger directly on the Image's own IsEnabled property. In other cases, the Button property we want to trigger on might not be inherited by the Image; in that case, we'd need to use a DataTrigger with the FindAncestor RelativeSource to bind to the containing button.
If you want something more generic, put this in your resources section for your window or UserControl .
<UserControl.Resources>
<Style x:Key="ImageEnabled" TargetType="Image">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.25"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
And in the actual button just do this
<Button>
<Image Source="{StaticResource LinkImage}" Style="{StaticResource ImageEnabled}"/>
</Button>
Here's a more generic style you can apply:
<Style TargetType="Button">
<Style.Resources>
<Style TargetType="Image">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
If you want the entire button greyed out, styling the button itself has worked for me. It seems to grey out all button content.
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value=".75"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
previous solutions only change opacity and not the color of the image, to gray out an image one need to convert the image to grayscale as follow. I did it for a toggleButton but the same method can be used on a button.
<ToggleButton>
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Content">
<Setter.Value>
<Image
RenderOptions.BitmapScalingMode="HighQuality"
RenderOptions.EdgeMode="Aliased"
Source="/Resources/imageForButton.png"
Stretch="UniformToFill" />
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content">
<Setter.Value>
<Image
RenderOptions.BitmapScalingMode="HighQuality"
RenderOptions.EdgeMode="Aliased"
Stretch="UniformToFill">
<Image.Source>
<FormatConvertedBitmap
x:Name="myImageFormat"
DestinationFormat="Gray8"
Source="/Resources/imageForButton.png" />
</Image.Source>
</Image>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>

Multiple ToggleButton image with different highlight image in WPF

I am very new to WPF and needed some pointers as to why this is not working correctly.
I am trying to make a maximize button that will change to a restore button when clicked. I thought a toggle button with 2 different styles that would be changed in the code behind could work. I am first trying to get the maximize button working and have ran into a problem. I get the error 'System.Windows.Controls.Image' is not a valid value for the 'System.Windows.Controls.Image.Source' property on a Setter. in my xaml. I seem to be not understanding something completely. Any help would be most helpful :)
Ryan
<Style x:Key="Maximize" TargetType="{x:Type ToggleButton}">
<Style.Resources>
<Image x:Key="MaxButtonImg" Source="/Project;component/Images/maxbutton.png" />
<Image x:Key="MaxButtonHighlight" Source="/Project;component/Images/maxbutton-highlight.png" />
</Style.Resources>
<Setter Property="ContentTemplate">
<Setter.Value>
<Image>
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{DynamicResource MaxButtonImg}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="{DynamicResource MaxButtonHighlight}"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Setter.Value>
</Setter>
</Style>
<ToggleButton Name="MaxButton" Width="31" Height="31" BorderThickness="0" Click="MaxButton_Click" Margin="0,0,10,0" Tag="Max"
Style="{DynamicResource Maximize}" />
My code behind would do something simple like this:
private void MaxButton_Click(object sender, RoutedEventArgs e)
{
ToggleButton tg = (ToggleButton)sender;
if ( tg.IsChecked == true) {
tg.Style = (Style)FindResource("Restore");
this.WindowState = WindowState.Maximized;
} else {
tg.Style = (Style)FindResource("Maximize");
this.WindowState = WindowState.Normal;
}
}
You don't want to change the image on mouse over. I added my images to a folder called Images in the project and set build action on the images to Resource.
<Window.Resources>
<Image x:Key="minImage" Source="/Images/min.png" Height="16" Width="16" />
<Image x:Key="maxImage" Source="/Images/max.png" Height="16" Width="16" />
<Style TargetType="{x:Type ToggleButton}" x:Key="minMaxButtonStyle">
<Setter Property="Content" Value="{DynamicResource minImage}" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="{DynamicResource maxImage}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<ToggleButton Style="{StaticResource minMaxButtonStyle}" />
</StackPanel>
</Window>

Resources