I'm trying to create a template button with a specific effect that can receive 2 background images as parameters (for button pushed and released). this template is implemented in a user control library :
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SwitchesLibrary">
<Style x:Key="PushButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border x:Name="MyBorder" CornerRadius="5" Background="{TemplateBinding Background}" BorderThickness="1">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<Border x:Name="ButtonPressedOnClick" Opacity="0" CornerRadius="5" Background="{DynamicResource ButtonPressed}" BorderThickness="1">
</Border>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ButtonPressedOnClick" Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0:0:0.05" Value="1.0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyBorder" Storyboard.TargetProperty="(FrameworkElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0:0:0.05" Value="0.0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1.0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="{DynamicResource ButtonReleased}"/>
</Style>
I use it in another user control library, but i don't know how to send the parameters {DynamicResource ButtonReleased} and {DynamicResource ButtonPushed}
:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/SwitchesLibrary;component/PushButton.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Button Name="ButtonA" Style="{StaticResource PushButton, ButtonPressed="Images/PushButtons/A_Pushed.png", ButtonReleased="Images/PushButtons/A_Released.png"}" HorizontalAlignment="Left" Height="44" VerticalAlignment="Top" Width="42" Click="ButtonA_Click" Margin="69,112,0,0"/>
The closest solution to 'parameterizing' a Style would be to override the image resources in the Button itself, but this would be rather verbose and cumbersome to do more than a few times:
<Button Style="{StaticResource PushButton}">
<Button.Resources>
<ImageBrush x:Key="ButtonPressed"
ImageSource="Images/PushButtons/A_Pushed.png" />
<ImageBrush x:Key="ButtonReleased"
ImageSource="Images/PushButtons/A_Released.png" />
</Button.Resources>
</Button>
If this is something you're going to use more than a couple times, it's worth investing a little more time upfront to make your image button easier to use. Wouldn't it be more convenient to type this instead?
<l:ImageButton NormalImage="Images/PushButtons/A_Released.png"
PressedImage="Images/PushButtons/A_Pushed.png" />
If you like the look of that, then the first step would be to write a simple ImageButton class and define dependency properties for the images representing the various button states:
public class ImageButton : Button
{
public static readonly DependencyProperty NormalImageProperty =
DependencyProperty.Register(
"NormalImage",
typeof(ImageSource),
typeof(ImageButton),
new PropertyMetadata(default(ImageSource)));
public ImageSource NormalImage
{
get { return (ImageSource)GetValue(NormalImageProperty); }
set { SetValue(NormalImageProperty, value); }
}
public static readonly DependencyProperty PressedImageProperty =
DependencyProperty.Register(
"PressedImage",
typeof(ImageSource),
typeof(ImageButton),
new PropertyMetadata(default(ImageSource)));
public ImageSource PressedImage
{
get { return (ImageSource)GetValue(PressedImageProperty); }
set { SetValue(PressedImageProperty, value); }
}
static ImageButton()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(ImageButton),
new FrameworkPropertyMetadata(typeof(ImageButton)));
}
}
The second step is to define a default style for your ImageButton. To do this, create a Themes\Generic.xaml resource dictionary in the project where ImageButton is declared. Make sure the Build Action is set to 'Page' in the Properties pane. Implement your default style here, for example:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:TestApp">
<Style TargetType="l:ImageButton"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="l:ImageButton">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Image x:Name="image"
Source="{TemplateBinding NormalImage}"
Stretch="None"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="image"
Property="Source"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=PressedImage}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Check your project's AssemblyInfo.cs file and make sure you have an attribute like this (and add it if you don't):
[assembly: ThemeInfo(
// Where theme specific resource dictionaries are located
// (used if a resource is not found in the page, or application
// resource dictionaries)
ResourceDictionaryLocation.None,
// Where the generic resource dictionary is located
// (used if a resource is not found in the page, app, or
// any theme specific resource dictionaries)
ResourceDictionaryLocation.SourceAssembly
)]
And now you're ready to go!
<l:ImageButton NormalImage="Images/PushButtons/A_Released.png"
PressedImage="Images/PushButtons/A_Pushed.png" />
Related
I have two Windows for an application. One of them is MainWindow and the other is for settings. SettingsWindow opens when settings button is clicked by using ShowDialog and setting its Owner to MainWindow.
On the SettingsWindow I have a button at the very bottom of the window and it changes the color to red when IsMouseOver is True and blue for False. But it doesn't change when the cursor is over the MainWindow. The image is below to be clear. How can I fix this problem?
CASE: The cursor is out of SettingsWindow but it keeps the red color, no change.
Xaml code:
<Window x:Class="AltoSS.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SettingsWindow"
Height="150"
Width="360"
WindowStyle="None"
AllowsTransparency="True"
WindowStartupLocation="CenterOwner">
<!-- Other control codes-->
<Button Grid.Row="2" Content="KAYDET"
FontSize="15"
FontWeight="Bold"
BorderBrush="Gray"
BorderThickness="0,2,0,2">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Window>
Alright, after doing some research, I couldn't find any logical reason for this to occur. It seems more like a bug to me. So if anyone knows exactly why this happens, let us know!
Anyway, I've come up with a workaround. Basically, we can use Show() and add some code to get closer to a modal behavior - like disabling the parent window until the dialog gets closed or the user has selected OK or Cancel for instance.
Example:
SettingsWindow settingsWindow = new SettingsWindow();
this.IsEnabled = false; //disables the main window
settingsWindow.Owner = this; // main window is the settings window owner
settingsWindow.Show();
settingsWindow.Closed += (o, e1) => { onWindowClosed(o,e1); }; // this is the close event
After subscribing for the settingsWindow closed event, we can now enable the parent window again when settingsWindow gets closed:
private void onWindowClosed(object sender, EventArgs e)
{
this.IsEnabled = true;
}
Triggers will now work correctly and parent window gets disabled until its child is closed.
I think you have to observe the mouse position manually. For this you could use the code behind posted by Peheje here.
I used this to program a working example. While leaving your window, the Button gets the correct style.
using System.Runtime.InteropServices;
using Point = System.Drawing.Point;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(ref Point lpPoint);
public bool IsMouseOverButton {
get { return _isMouseOverButton; }
set {
if (value == _isMouseOverButton) return;
_isMouseOverButton = value;
OnPropertyChanged();
}
}
public SettingsWindow()
{
InitializeComponent();
new Thread(() =>
{
while (true)
{
//Logic
Point p = new Point();
GetCursorPos(ref p);
//Update UI
Application.Current.Dispatcher.Invoke(() =>
{
double btnLeft = DlgWindow.Left;
double btnRight = btnLeft + DlgBtn.ActualWidth;
double btnBottom = DlgWindow.Top + DlgWindow.ActualHeight;
double btnTop = btnBottom - DlgBtn.ActualHeight;
IsMouseOverButton =
p.X >= btnLeft && p.X <= btnRight &&
p.Y >= btnTop && p.Y <= btnBottom;
});
//async wait (non blocking)
(new ManualResetEvent(false)).WaitOne(100);
}
}).Start();
}
xaml
<Window x:Name="DlgWindow"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
AllowsTransparency="True">
<Button x:Name="DlgBtn"
Height="50"
VerticalAlignment="Bottom"
BorderBrush="Gray"
BorderThickness="0,2,0,2"
Content="KAYDET"
FontSize="15"
FontWeight="Bold">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOverButton}" Value="True">
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="White" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
This works for me: Define a style resource (for the button) under settings Window.Resources - This style then sets the new Template (a border), the default background as blue, and the IsMouseOver trigger to change it to red. Reference the style either explicitly for implicitly (both worked for me).
Link to small test project: https://1drv.ms/u/s!AhlMAmchX3R6nDJ1MXS6DxlRXtnA
<Window x:Class="IsMouseOverTriggerSecondWindow.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:IsMouseOverTriggerSecondWindow"
mc:Ignorable="d"
Title="SettingsWindow" Height="170" Width="330">
<!-- my settings window button style-->
<!-- defined as a resource in SettingsWindow.xaml, so it doesnt effect MainWindow -->
<Window.Resources>
<Style TargetType="Button" >
<Setter Property="Background" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TextBlock Text="This is the settings window" />
<Button Content="KAYDET" Height="30" VerticalAlignment="Bottom" Foreground="White" FontWeight="Bold" />
</Grid>
</Window>
I am currently using Blend and some tutorials I found online to try to make my own button user control. Normally, I would just use a custom style and apply it to the controls I want, but I wrote in some dependency properties as well so I decided to write my own user control.
Something that I can't get my head around is how to set the Content property without overwriting the styling of the button control. I thought it might have been my code, but I started brand new with another button and I have the same thing happen - when the Content property is set, the button simply turns white and has black text in the upper left corner.
Here is the XAML code that Blend generated for me:
<UserControl x:Class="MyUI.Controls.MyButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="100">
<UserControl.Resources>
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle/>
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True"/>
<Trigger Property="IsDefaulted" Value="True"/>
<Trigger Property="IsMouseOver" Value="True"/>
<Trigger Property="IsPressed" Value="True"/>
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Button Content="Button" Height="25" Style="{DynamicResource MyButtonStyle}" Width="100"/>
</Grid>
Now, if I reference the button in my main window like this, it reverts any styling that was done within the user control:
<local:MyButton Content="test" />
What do I need to change in order to make the button accept a different Content tag?
What you need is to connect your UserControl level Content property to your Button level Content property. By default UserControl's Content property is its only child element, which is Grid in your case. You can either create your own Content property or another one with different name. In your UserControl's .cs file:
/// <summary>
/// Interaction logic for MyButton.xaml
/// </summary>
public partial class MyButton : UserControl
{
public new static DependencyProperty ContentProperty =
DependencyProperty.Register("Content", typeof (object),
typeof (MyButton));
public new object Content
{
get { return GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
public MyButton()
{
InitializeComponent();
}
}
On your UnserControl's Xaml:
<Button Content="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
Height="25" Style="{DynamicResource MyButtonStyle}" Width="100"/>
Now Button's Content binds to your UserControl level Content property.
I am trying to create a custom control for a text block that when moused over, a border will appear. I am pretty new to WPF and have only made some very simple custom controls. I need to implement this in a XAML UserControl.
Any suggestions would be greatly appreciated. Thanks again, StackOverflow.
EDIT: I am going to have to bind a persistence property to several different controls, so I really need to do this in a custom control. This is what I have, and it isn't working:
xmlns:customControls="clr-namespace:****.CustomControls"
....
<customControls:MouseOverBorder>
<TextBlock Style="{StaticResource ResourceKey=HomePageButtonText}"
Height="100"
Width="100"
Margin="5"
Text="View Reports" />
</customControls:MouseOverBorder>
And the UserControl:
<UserControl
x:Class="****.MouseOverBorder"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="MouseOverBorder" TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="3" />
<Style.Triggers>
<Trigger Property="Border.IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Border Style="{DynamicResource MouseOverBorder}" BorderThickness="1" CornerRadius="3" SnapsToDevicePixels="True"/>
No need to make a UserControl. I've managed to accomplish this with the following markup:
<Border Style="{DynamicResource BorderStyle1}" BorderThickness="1" CornerRadius="3" >
<TextBlock Text="TextBlock" />
</Border>
Here's the style:
<Style x:Key="BorderStyle1" TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="3"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="#FF123BBA"/>
</Trigger>
</Style.Triggers>
</Style>
EDIT:
Still don't get it why do you need a UserControl (please don't call it custom control - these are different things), but let's consider your example.
When you write the following
<customControls:MouseOverBorder>
<TextBlock Style="{StaticResource ResourceKey=HomePageButtonText}"
Height="100"
Width="100"
Margin="5"
Text="View Reports" />
</customControls:MouseOverBorder>
you are actually setting MouseOverBorder.Content property. Originally it's Content is defined in MouseOverBorder.xaml file. So you are replacing all your UserControl structure with TextBlock. But still I got your idea and have solution for it.
First, add custom DependencyProperty and CLR wrapper for it to MouseOverBorder class:
public static readonly DependencyProperty MyContentTemplateProperty =
DependencyProperty.Register("MyContentTemplate", typeof(DataTemplate), typeof(MouseOverBorder), null);
[Browsable(true)]
[Category("Other")]
public DataTemplate MyContentTemplate
{
get { return (DataTemplate)GetValue(MyContentTemplateProperty); }
set { SetValue(MyContentTemplateProperty, value); }
}
Second, make something inside MouseOverBorder use this property, e.g.
<ContentPresenter ContentTemplate="{Binding MyContentTemplate, ElementName=userControl}"/>
<!-- userControl is the Name of MouseOverBorder, defined in xaml -->
At last, you can use your UserControl as following:
<customControls:MouseOverBorder>
<customControls:MouseOverBorder.MyContentTemplate>
<DataTemplate>
<TextBlock Style="{StaticResource ResourceKey=HomePageButtonText}"
Height="100"
Width="100"
Margin="5"
Text="View Reports" />
</DataTemplate>
</customControls:MouseOverBorder.MyContentTemplate>
</customControls:MouseOverBorder>
I’d like to find out how to bind the opacity of the object that is part of the ControlTemplate to the object that is part of another ControlTemplate.
I tried this but it is not doing anything.
Image x:Name="PART_IconHover" Source="{Binding IconHover}" Opacity="{Binding Opacity, ElementName=border, Mode=OneWay}" />
Below is the code of two ControlTemplates:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" BorderBrush="#FF6E6E6E" BorderThickness="0.5" Opacity="0" Background="#00000000">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="border">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true"/>
<Trigger Property="ToggleButton.IsChecked" Value="true"/>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
I want to bind the opacity to the image in the ControlTemplate below
<ControlTemplate x:Key="ThumbnailContainerTemplate" TargetType="{x:Type ContentControl}">
<Border x:Name="PART_Border" BorderThickness="1" BorderBrush="#FFd9d9d9" Opacity="0" />
<Grid Margin="10">
<Image x:Name="PART_IconHover" Source="{Binding IconHover}" Opacity="{Binding Opacity, ElementName=border, Mode=OneWay}" />
</Grid>
Any ideas are highly appreciated. Thank you in advance!
I don't think that you can bind to elements inside templates like that. The binding system isn't able to find them.
If you just need a numeric value somewhere in your xaml that you want everything to use, you can just add one like this:
<sys:Double x:Key="Opacity">.5</sys:Double>
Then just have everything bind to that. You'll need to add the sys namespace
xmlns:sys="clr-namespace:System;assembly=mscorlib"
As mdm20 said, you can't bind to elements inside templates from outside the template since a template is just used to build up a control. For instance, several Buttons could use the Template in your example so which Button would the ContentControl bind to?
I can't see a re-usable solution to this but one thing that comes to mind is to set the Binding in code behind once the Controls have finished loading like this
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Border border = myButton.Template.FindName("border", myButton) as Border;
Image PART_IconHover = contentControl.Template.FindName("PART_IconHover", contentControl) as Image;
Binding opacityBinding = new Binding("Opacity");
opacityBinding.Mode = BindingMode.OneWay;
opacityBinding.Source = border;
PART_IconHover.SetBinding(Image.OpacityProperty, opacityBinding);
}
Update
Two Controls binding to the border in a Button template. The binding is made in the Control_Loaded event handler.
<ContentControl ...
Loaded="Control_Loaded">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="Template" Value="{StaticResource contentTemplate}"/>
</Style>
</ContentControl.Style>
</ContentControl>
<ContentControl ...
Loaded="Control_Loaded">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="Template" Value="{StaticResource contentTemplate}"/>
</Style>
</ContentControl.Style>
</ContentControl>
private void Control_Loaded(object sender, RoutedEventArgs e)
{
Border border = myButton.Template.FindName("border", myButton) as Border;
Control control = sender as Control;
Image PART_IconHover = control.Template.FindName("PART_IconHover", control) as Image;
Binding opacityBinding = new Binding("Opacity");
opacityBinding.Mode = BindingMode.OneWay;
opacityBinding.Source = border;
PART_IconHover.SetBinding(Image.OpacityProperty, opacityBinding);
}
I want Image button with two state(normal , mouse over). that button must change image with Mouse Over event trigger automatically.
this image button must be a user control. Also i want to set image for each state form code in which form i use that user control.
Solution is using a template with "Value Converter" but i don't know how?
Why must this image button be a user control? If a regular button with a new control template is fine, this should work:
<Button>
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image Name="HoverImage" Source="hover_image.png" Visibility="Hidden" />
<Image Name="DefaultImage" Source="default_image.png" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="DefaultImage" Property="Visibility" Value="Hidden" />
<Setter TargetName="HoverImage" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
If you need a simple rollover effect, you don't need a template for it.. article below has a solution to it..
http://www.c-sharpcorner.com/Resources/Detail.aspx?ResourceId=706
In this article user uses SolidColorBrush, you can use ImageBrush to set image as background of button.
I found This on Code-project-Article(Cool example)
http://www.codeproject.com/KB/WPF/WPF_xaml_taskbar_window.aspx
First He create Wpf-Custom-control(you can create class inherit from Button like this)
public class ImageButton : Button
{
private string cornerRadius;
public string CornerRadius
{
get { return cornerRadius; }
set { cornerRadius = value; }
}
private string highlightBackground;
public string HighlightBackground
{
get { return highlightBackground; }
set { highlightBackground = value; }
}
private string pressedBackground;
public string PressedBackground
{
get { return pressedBackground; }
set { pressedBackground = value; }
}
}
As second step you must Create template in resource-dictionary(here is code)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Phone.Controls">
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type local:ImageButton}">
<ControlTemplate.Resources>
<Storyboard x:Key="MouseOverButton">
<ThicknessAnimation Storyboard.TargetName="ButtonBackgroundBorder"
Storyboard.TargetProperty="(Control.Margin)"
Duration="0:0:0.05"
FillBehavior="Stop"
From="0,0,0,0" To="2,2,2,2"
AutoReverse="True" />
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="ButtonOuterGrid">
<Border x:Name="ButtonBackgroundBorder"
CornerRadius="{Binding Path=CornerRadius, RelativeSource={RelativeSource TemplatedParent}}"
Background="{Binding Path=HighlightBackground, RelativeSource={RelativeSource TemplatedParent}}"
BorderBrush="Black"
BorderThickness="0.8"
Opacity="0">
<Border.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="#FFFFFFFF" GlowSize="2.75" Noise="0.20"/>
</Border.BitmapEffect>
</Border>
<Border x:Name="ButtonEdgesBorder" CornerRadius="{Binding Path=CornerRadius, RelativeSource={RelativeSource TemplatedParent}}"
Opacity="1"
BorderBrush="Transparent"
BorderThickness="0" />
<Border x:Name="ButtonContentBorder"
CornerRadius="{Binding Path=CornerRadius, RelativeSource={RelativeSource TemplatedParent}}"
Opacity="1"
BorderThickness="1">
<ContentPresenter x:Name="ContentText"
Width="Auto" Height="Auto"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.Setters>
<Setter Property="Opacity" TargetName="ButtonBackgroundBorder" Value="1"/>
<Setter Property="TextElement.Foreground" TargetName="ContentText" Value="Black"/>
</Trigger.Setters>
</Trigger>
<EventTrigger RoutedEvent="Grid.MouseEnter"
SourceName="ButtonOuterGrid">
<BeginStoryboard Storyboard="{StaticResource MouseOverButton}"/>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="ImageButton" TargetType="{x:Type Button}">
<Setter Property="Template" Value="{StaticResource ButtonTemplate}" />
</Style>
And this is last Step, in xaml file you must insert this custom-control
<ImageButton x:Name="btnConfigs"
Style="{StaticResource ImageButton}"
Width="25" Height="25"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Margin="0,31.125,16.418,0">
<Image x:Name="ImgConfigs"
Stretch="Fill"/>
</ImageButton >
and in cs file do this
this.ImgConfigs.Source="any imag-source"
also we can change this image-source on btnconfig-click event
With special thanks from Murray-Foxcroft for create that article