How to change Button's Image when mouse is over in XAML? - wpf

I have a button contained two ellipse (Outer ellipse and Inner
ellipse) and center of these ellipes is an image i want to make this
button like rounded button,and i want to change image when mouse in
over the button and below is my xaml code I'm new in WPF and XAML and
i know it's not perfect way but any tips can help me to improve my
knowledge
<Style x:Key ="roundButton" TargetType ="{x:Type Button}">
<Setter Property ="Foreground" Value ="Black"/>
<Setter Property ="FontWeight" Value ="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border" BorderThickness="0" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border">
<Setter.Value>
<ImageBrush ImageSource="/Images/505050.png"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property ="Template">
<Setter.Value>
<ControlTemplate TargetType ="{x:Type Button}">
<Grid>
<Ellipse Name ="OuterRing" Width ="30" Height ="30" Fill ="Black"/>
<Ellipse Name ="InnerRing" Width ="27" Height ="27" Fill ="WhiteSmoke"/>
<Image Name="im"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property ="IsMouseOver" Value ="True">
<Setter TargetName ="OuterRing" Property ="Fill" Value ="black"/>
<Setter TargetName ="InnerRing" Property ="Fill" Value ="black"/>
</Trigger>
<Trigger Property ="IsPressed" Value ="True">
<Setter TargetName ="OuterRing" Property ="Height" Value ="33"/>
<Setter TargetName ="OuterRing" Property ="Width" Value ="33"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It's not working,when mouse is over only ellipses color and size
changed but image stay as it beside even if it's work it's not really
useful because i want to use this style on many button so in previous
code i already gave it image source so it's not helpful, below is my
Design XAML code
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="4*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="WhiteSmoke" Margin="10,10,10,0" CornerRadius="5">
<StackPanel Orientation="Horizontal">
<Button x:Name="btnDataBase" Margin="20,0,0,0" Style="{DynamicResource roundButton}">
<Image Source="/Images/5050.png" Width="20" Height="20"/>
</Button>
</StackPanel>
</Border>
</Grid>
As i said I'm new in XAML and WPF and all above codes got from many
searching on google so i don't know what's the better way to do this
button,help me please
this image for the rounded button when mouse is not over
and this image for the rounded button when mouse is over

A simple Style Trigger to change the Image source when the IsMouseOver property is true should work. Try something like this:
<Button Style="{DynamicResource roundButton}">
<Image Style="{StaticResource btnImageStyle}" Width="20" Height="20"/>
</Button>
<Style TargetType="{x:Type Image}" x:Key="btnImageStyle">
<Setter Property="Source" Value="Image1"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Source" Value="Image2"/>
</Trigger>
</Style.Triggers>
</Style>

Related

WPF: Change a value from a template

I want a value which is inside a template to change while some trigger happens. I can't access it through the style trigger's for some reason. How do I achieve that?
example:
<Style TargetType="Button" x:Key="iconButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Margin="5">
<Ellipse Width="45" Height="45" Fill="White" Opacity="0"/>
<TextBlock Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center">hello</TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--TODO - change the "opacity" of the ellipse.
Maybe binding is necessary? -->
</Trigger>
</Style.Triggers>
</Style>
I would like to change the opacity property of the ellipse (which is inside the style's template) while overing the button with the mouse.
How can this be achieved?
Instead of Style Triggers use ControlTemplate Triggers. Refer below code.
<Style TargetType="Button" x:Key="iconButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Margin="5">
<Ellipse Width="45" x:Name="EllipseControl" Height="45" Fill="White" Opacity="0"/>
<TextBlock Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center">hello</TextBlock>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="EllipseControl" Property="Opacity" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

How to show current position of a slider over the thumb always

How to show a slider control with a tooltip/label under the thumb showing the value (timespan) always while it moves with/without user dragging.
I tried AutoToolTipPlacement="BottomRight" AutoToolTipPrecision="3" on my slider.
But Tooltip gets displayed only when i drag the thumb. I want that shown even when i invoke playing slider with a button control.(like video player)
The point is to reduce the size of my usercontrol and avoid extra labels for timers or position.
If i am in the wrong direction, please suggest me better ideas. Thanks!
You can re-style the Thumb to show this effect. Below is a sample that makes a circular Thumb with the .Value property of the parent Slider showing up inside the circle.
<Style TargetType="{x:Type Thumb}">
<Setter Property="Focusable" Value="false"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Height" Value="20"/>
<Setter Property="Width" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Canvas SnapsToDevicePixels="true">
<Grid Height="20" Width="20">
<Ellipse x:Name="Background"
Fill="#FFA3A3A3"
Height="20" Width="20"
Stroke="#FFDADADA"/>
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="Black"
FontSize="9"
Text="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type Slider}}, Converter={StaticResource ConvertToIntegerConverter}}"/>
</Grid>
</Canvas>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Fill" TargetName="Background"
Value="#FFDADADA"/>
</Trigger>
<Trigger Property="IsDragging" Value="true">
<Setter Property="Fill" TargetName="Background"
Value="#FFF2F2F2"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="Background"
Value="#FFF2F2F2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I've used an IValueConverter to make sure the the value displayed is always an integer, since the normal .Value property is a decimal. You would want to use your own converter to properly format the information that you want displayed.
You can make the text or numbers appear wherever you want by re-styling the Thumb.
EDIT:
If you want to show the text above or below the actual thumb, it's a pretty minor change to the styling:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Ellipse x:Name="Background"
Fill="#FFA3A3A3"
Height="20" Width="20"
Stroke="#FFDADADA"/>
<TextBlock Grid.Row="1" HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="White"
FontSize="9"
Text="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type Slider}}, Converter={StaticResource ConvertToIntegerConverter}}"/>
</Grid>

"Pushed" effect on button press

I have circular button as
XAML for that is,
<!--round button-->
<Style x:Key ="roundButtonTemplate" TargetType ="{x:Type Button}">
<Setter Property ="Margin" Value ="10,0,10,10"/>
<Setter Property ="Template">
<Setter.Value>
<ControlTemplate TargetType ="{x:Type Button}">
<Grid>
<Ellipse x:Name ="OuterRing" Width ="40" Height ="40" Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property ="IsPressed" Value ="True">
<Setter TargetName ="OuterRing" Property ="Height" Value ="30"/>
<Setter TargetName ="OuterRing" Property ="Width" Value ="30"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And I have applied it as,
<Button Style="{StaticResource roundButtonTemplate}" Click="button_Click" Background="#CC41B1E1" Width="42" Height="42" Margin="0,0,10,0">
<Image Height="24" Width="24" Source="/Images/add.png" />
</Button>
Now the problem is when I press the button only the circle shrinks but the image remains as it is. I want the whole button to shrink with image as well to give it a perfect "Pushed" effect.
Any idea what is getting wrong?
Instead of changing size to some fixed value in you template apply ScaleTransform to main Grid of your template
<ControlTemplate TargetType ="{x:Type Button}">
<Grid RenderTransformOrigin="0.5,0.5" x:Name="RootGrid">
<Ellipse x:Name ="OuterRing" Width ="40" Height ="40" Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property ="IsPressed" Value ="True">
<Setter TargetName="RootGrid" Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="0.9" ScaleY="0.9"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
don't forget to set RenderTransformOrigin="0.5,0.5"

How to change part of the datatemplate background

I have a ListBox, its DateTemplate like this:
<Grid Margin="30,0,0,0" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Source="{Binding Path=IconSource}"/>
<TextBlock Grid.Column="1" Background="{x:Null}" Text="{Binding Path=DisplayText, Mode=Default}" Foreground="Black"/>
</Grid>
and this is the ItemContainerStyle:
<Style x:Key="Test" TargetType="ListBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border" SnapsToDevicePixels="True">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="Blue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
When one ListBoxItem is selected, is it possible not to set the image's background?
Like in Intellisense of VS, the icon of the API doens't have background.
The simplest thing is to put your image inside another Grid, and set the Grid's Background to the background color you would like the image to have - then when you change the Background of the parent Border, the image's parent grid will protect it from the background color change.
I am not completely sure if this is what you meant, but I would recommend to use no data template but instead do all the necessary data binding with the elements of the item container control template. This is possible as the item container and the data template actually share the same data context. In case of a ListBoxItem, this would look like this:
<ControlTemplate x:Key="ListBoxItemTemplate" TargetType="ListBoxItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource}" Height="50" Margin="0,0,5,0"/>
<Border x:Name="Border" VerticalAlignment="Center" Grid.Column="1">
<TextBlock Text="{Binding Name}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="Blue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
You would reference this template in the ItemsContainerStyle that is set on your ListBox.
In summary: do not use a data template but incorporate it in the ItemContainerStyle. Thus you can leave the background of the Image element untouched.
Hope this helps.

Change color of MenuItem on MouseOver

I want to change the color of a MenuItem at mouseOver. I need also rounded borders, an image and a textBox. When I set the style all is ok only the mouseOverEvent is doing anything, the background doesnot change. My code is:
<Style x:Key="BaseStyle" TargetType="MenuItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="#0a99f3" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Setter Property="Background" Value="#0a99f3" />
</Trigger>
</Style.Triggers>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Grid>
<Border Name="MainBorder" BorderThickness="2,2,2,0" CornerRadius="8,8,8,8" Margin="0,0,1,0" BorderBrush="AliceBlue">
<Grid>
<TextBlock Text="Info" Margin="30,10,0,0" FontFamily="Arial" FontSize="14" FontWeight="Bold" />
<Image Width="15" Height="15" Source="menu.PNG" Margin="-100,0,0,0" />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Hope anybody know what I am missing. Thanks!
You're overwritting the Template, but not using the Background Color anywhere in it so the value never gets applied.
Set the Background Color in your MenuItem Template
<ControlTemplate TargetType="{x:Type MenuItem}">
<Grid Background="{TemplateBinding Background}">
You are not binding the Background anywhere in your template so changing that property has no effect.

Resources