Changing the foreground of button text and image on mouse over - c#

I have a button defined as follows:
<Button x:Name="ContactLink" Canvas.Left="20" Canvas.Top="223" Style="{StaticResource HyperlinkButton}" Click="ContactLink_Clicked">
<WrapPanel>
<Rectangle Width="15" Height="15">
<Rectangle.Fill>
<VisualBrush Stretch="Fill" Visual="{StaticResource appbar_new_window}" />
</Rectangle.Fill>
</Rectangle>
<TextBlock Margin="5 0 0 0" FontWeight="SemiBold" Text="GET IN TOUCH" />
</WrapPanel>
</Button>
As the title says, I would like to define a style which changes the foreground of TextBlock and of the VisualBrush. So far, I have the following style, which doesn't work. It changes the foreground of the textblock and the definition of the BlackBrush resource.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="HyperlinkButtonTemplate" TargetType="{x:Type Button}">
<WrapPanel>
<TextBlock Cursor="Hand">
<ContentPresenter />
</TextBlock>
</WrapPanel>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter Property="TextBlock.Foreground" Value="#0071bc" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="HyperlinkButton" TargetType="{x:Type Button}">
<Setter Property="Template" Value="{StaticResource HyperlinkButtonTemplate}" />
</Style>
</ResourceDictionary>
Any help on getting it to work would be very much appreciated.

You just need to remove the SolidColorBrush you defined inside the trigger
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter Property="TextBlock.Foreground" Value="#0071bc" />
</Trigger>

Probably too late, but I had the same issue and managed to solve it.
Just set name property of the TextBlock then you can refer to that name in the trigger.
<TextBlock Cursor="Hand" Name="MyTextBlock">
<ContentPresenter />
</TextBlock>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter TargetName="MyTextBlock" Property="Foreground" Value="#0071bc"/>
</Trigger>
</ControlTemplate.Triggers>

Related

Change control background when mouse is over it

I have found different pieces of codes that are supposed to change the background of a control when the mouse hovers it. I haven't been able to make any of them work. This is the piece of code that I'm using right now. I don't know what I'm missing, I'm specifying everything.
<Window.Resources>
<Style x:Key="HoverButton" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#FFA9DE4E"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
Im also specifying the Style I want to apply to the specific control, in this case is a button.
<!-- Start button -->
<Button x:Name="btnStart" Style="{StaticResource HoverButton}" Content="Start" Margin="503,411,10,10" FontWeight="Bold" BorderBrush="#FFA9DE4E" Click="BtnNext_Click" Foreground="#FFA9DE4E" Background="#FF222831">
<Button.Effect>
<DropShadowEffect Color="#FFA9DE4E" ShadowDepth="1" BlurRadius="20" Direction="320"/>
</Button.Effect>
</Button>
When I hover the button nothing changes.
Try to modify the button template like this:
<Button Content="Button" HorizontalAlignment="Center" Click="Button_Click" VerticalAlignment="Center" Width="75">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="bdr_main" BorderThickness="1" BorderBrush="Black" Background="LightGray">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bdr_main" Property="Background" Value="#FFA9DE4E"/>
</Trigger>
//You can also change the color at the click like this:
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="bdr_main" Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
By modifying the template, you can stylize your button as you wish.
Hoping to help you.

WPF issue with button background image

I have my wpf button as follows
<Button x:Name="helpButton" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="552,201,95,726" Width="32" Height="32" BorderThickness="0" Click="helpButton_Click">
<Button.Background>
<ImageBrush ImageSource="/Images/help-icon1.png"></ImageBrush>
</Button.Background>
</Button>
On window load I am able to see the image perfectly but when I hover the mouse I am not able to see the image
So can some one help me
A more sensible approach to start would be by using <Button.Template> instead of <Button.Background>
<Button x:Name="helpButton">
<Button.Template>
<ControlTemplate>
<Border HorizontalAlignment="Center" VerticalAlignment="Center" >
<Image Source="/Images/help-icon1.png" Width="32" Height="32"/>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
Additionally style the button border with for example a hover effect with Trigger and Setter
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="buttonBorder" Property="BorderBrush" Value="Green"></Setter>
<Setter TargetName="buttonBorder" Property="BorderThickness" Value="1" />
</Trigger>
</ControlTemplate.Triggers>
which you will add like so:
<Button x:Name="helpButton" Height="35">
<Button.Template>
<ControlTemplate>
<Border Name="buttonBorder" HorizontalAlignment="Center" VerticalAlignment="Center" >
<Image Source="/Images/help-icon1.png" Width="32" Height="32"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="buttonBorder" Property="BorderBrush" Value="Green"/>
<Setter TargetName="buttonBorder" Property="BorderThickness" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
It is really strange why it is not possible to see image when button is hovered. Default style always shows Content(in your case, image). So I suggest you just use default style for your button:
<Button Style="{ x:Null}">
<Image Source="/images/images.jpg"></Image>
</Button>
Or just override behavior of template when mouse is over button:
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Green"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderBrush="Black" BorderThickness="1">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--Do not do any actions here to see your image-->
</Trigger>
</Style.Triggers>
</Style>
In this case, there is no actions when mouse is over your button.

Clicking on WPF ToggleButton changes other ToggleButtons values

I have a simple ToggleButton with Style triggers to change the button's image based on the state of IsChecked. This is working fine for one button. However when I add more than one button to a grid, clicking one of the ToggleButtons changes the state of the others. Should I use some other trigger type instead of one based on the botton's style?
Here is the xaml block to lay out the three ToggleButtons:
<Grid Height="362" Width="259">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ToggleButton Style="{StaticResource TogglebuttonStyle}" IsChecked="{x:Null}" IsThreeState="True"
Width="15" Height="15" Grid.Row="0" Grid.Column="0"/>
<ToggleButton Style="{StaticResource TogglebuttonStyle}" IsChecked="{x:Null}" IsThreeState="True"
Width="15" Height="15" Grid.Row="1" Grid.Column="0"/>
<ToggleButton Style="{StaticResource TogglebuttonStyle}" IsChecked="{x:Null}" IsThreeState="True"
Width="15" Height="15" Grid.Row="2" Grid.Column="0"/>
</Grid>
And here is the Style with triggers:
<Style x:Key="TogglebuttonStyle" TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImagePlus}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImageMinus}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImageNeutral}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
I'll call this a workaround, but now each button retains its own state:
I found if I moved my Style block out of App.xaml (within the tag) and defined style triggers for each button, the problem behavior went away. Since I'm fairly new to WPF/XAML I'm not sure if it's an actual solution or a hacky workaround. It seems redundant to specify things this way.
<ToggleButton IsChecked="True" IsThreeState="True"
Width="25" Height="25" Grid.Row="2" Margin="-1,19,1,-19">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImagePlus}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImageMinus}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource ImageNeutral}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
After doing some more research, I found I had to specify that the style not be shared.
<Style x:Key="ToggleButtonStyle" x:Shared="False" /Style>
The problem is that the setter instantiates one instance of the Image control, which can have only one parent. When then button goes into the "ImagePlus" state, all's well. When a second button goes into that state, that Image control gets moved to the new parent, leaving the old one bereft.
This is one reason why XAML has templates: When a template is instantiated, a new instance of that snippet of visual tree gets instantiated. Presto, no sharing issues.
With some resources you can set x:Shared="False" on the resource and get around this issue. I couldn't find a way to make that work here (I've not yet gotten around to figuring out the principle behind exactly when that works and when not). So I did it with DataTemplates instead:
<Style x:Key="TogglebuttonStyle" TargetType="ToggleButton" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{StaticResource ImagePlus}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{StaticResource ImageMinus}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{StaticResource ImageNeutral}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>

Set the content of the textblock within toggle button

I am trying to set the content of the textblock (as shown below) when the IsChecked property has changed for the toggle button. I have tried multiple ways but unable to get it to work.
<ToggleButton VerticalAlignment="Center" Margin="4 0 0 0" Background="{DynamicResource AccentColorBrush}" Name="toggle">
<StackPanel Orientation="Horizontal">
<Rectangle Width="20" Height="20" Fill="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{StaticResource appbar_starwars_jedi}" />
</Rectangle.OpacityMask>
</Rectangle>
<TextBlock x:Name="SimulationToggleButtonText" Margin="4 0 0 0" VerticalAlignment="Center" Text="Start Simulation">
</TextBlock>
</StackPanel>
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Foreground" Value="Green"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="Stop Simulation"/>
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
You need to use a control template, please see this adjusted code:
<ToggleButton VerticalAlignment="Center" Margin="4 0 0 0" Background="{DynamicResource AccentColorBrush}" Name="toggle">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Foreground" Value="Green"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<StackPanel Orientation="Horizontal">
<Rectangle Width="20" Height="20" Fill="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{StaticResource appbar_starwars_jedi}" />
</Rectangle.OpacityMask>
</Rectangle>
<TextBlock x:Name="SimulationToggleButtonText" Margin="4 0 0 0" VerticalAlignment="Center" Text="Start Simulation">
</TextBlock>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="SimulationToggleButtonText" Property="Text" Value="Stop Simulation"/>
<Setter TargetName="SimulationToggleButtonText" Property="Foreground" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
The problem is that your ToggleButton style doesn't have access to any controls that are a part of the ToggleButton content. By moving the controls and triggers to the template, they are in the same scope.

Change Image source inside a Button template

I have a button in WPF application. I am presenting an image instead of a button.
When my app comes up , all the controls are disabled , until a user logs in. I want my app to start with button that it's image is gray-->disabled . and when someone logged in , i want to change to color image.but i can't access the image in the button's template. can anyone help? thank you.
the code of my button -
<Button Height="55" Background="CornflowerBlue" Foreground="White" FontWeight="Normal" Name="Button_Cancel" FontSize="12" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="55" Click="Button_Cancel_Click">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel >
<Image Source="Images/myImage.png" Name="Image_Cancel"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Button.BitmapEffect" >
<Setter.Value>
<DropShadowBitmapEffect Color="LightGray" Direction="300" ShadowDepth="5" >
</DropShadowBitmapEffect>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Button.RenderTransform">
<Setter.Value>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="0.970" ScaleY="0.970">
</ScaleTransform>
<!--<SkewTransform AngleY="2" CenterY="-100"/>-->
</TransformGroup>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
You can hook up the image with the IsEnabled property via trigger, then you probably don't need code behind access.
<Image>
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="Images/Image_Normal.png" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Source" Value="Images/Image_Disabled" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
You can do this..
<StackPanel >
<Image x:name="MyImage" Source="Images/myImage.png" Name="Image_Cancel"/>
</StackPanel>
and when you want to to access the image or modify it
<Setter Property = "Source" TargetName = "MyImage" value = "something"/>

Categories

Resources