How to create a simple WPF UserControl button with custom enabled/disabled images?
I am a bit new to WPF and XAML, just learning now.
I found a quick-n-dirty code by some previous developer:
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
<Border Name="buttonBorder" Background="{TemplateBinding Background}">
<Border.Effect>
<DropShadowEffect Opacity="0.0" />
</Border.Effect>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="buttonBorder" Property="Effect">
<Setter.Value>
<DropShadowEffect Opacity="0.8" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseCaptured" Value="true">
<Setter TargetName="buttonBorder" Property="Effect">
<Setter.Value>
<DropShadowEffect Opacity="0.8" Direction="135"
ShadowDepth="3" BlurRadius="1" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="buttonBorder" Property="Background">
<Setter.Value>
<ImageBrush ImageSource="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}" />
</Setter.Value>
</Setter>
<Setter TargetName="buttonBorder" Property="Effect">
<Setter.Value>
<DropShadowEffect Opacity="0.开发者_Python百科0"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Basically it is just a template for a button with a basic mouseover effect and the image for disabled state bound to Tag (seems an ugly solution).
I want to create a custom button which works pretty the same, but I want to expose two custom properties: NormalImage and DisabledImage. Those properties should be of type string not Uri. I want to use the path to image just "apply.png" and not "pack://application:,,,/Resources/Apply.png". I guess, to have such custom properties I need a UserControl with dependency properties?
Basically, I want to use the button as follows:
<MyImageButton NormalImage="apply.png" DisabledImage="apply_disabled.png"/>
Maybe NormalImage/DisabledImage will be bound to something later but that's unlikely.
I could not find any example which implements such a basic button with custom properties, there are only some fancy buttons and controls online. Maybe I am just using incorrect keywords...
Could anyone point me to the right article or throw some simple piece of code to play with?
WPF is so complicated for beginners, sometimes it just does not work as expected, for example I still do not understand why I can add Trigger tag to ControlTemplate, but I cannot add Trigger tag straight to UserControl...
You could also use a UserControl
which is a bit messy since your button will be encapsulated, would look something like this:
Xaml:
<UserControl x:Class="Test.ImageButton"
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="300" d:DesignWidth="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Button Name="button" Click="button_Click" Width="50" Height="50">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="buttonBorder">
<Border.Effect>
<DropShadowEffect Opacity="0.0" />
</Border.Effect>
<Border.Child>
<Image Name="img" Source="{Binding NormalImage}"/>
</Border.Child>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="buttonBorder" Property="Effect">
<Setter.Value>
<DropShadowEffect Opacity="0.8" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseCaptured" Value="true">
<Setter TargetName="buttonBorder" Property="Effect">
<Setter.Value>
<DropShadowEffect Opacity="0.8" Direction="135"
ShadowDepth="3" BlurRadius="1" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="img" Property="Source" Value="{Binding DisabledImage}"/>
<Setter TargetName="buttonBorder" Property="Effect">
<Setter.Value>
<DropShadowEffect Opacity="0.0"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</UserControl>
Code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Test
{
/// <summary>
/// Interaction logic for ImageButton.xaml
/// </summary>
public partial class ImageButton : UserControl
{
public ImageSource DisabledImage
{
get { return (ImageSource)GetValue(DisabledImageProperty); }
set { SetValue(DisabledImageProperty, value); }
}
public static readonly DependencyProperty DisabledImageProperty =
DependencyProperty.Register("DisabledImage", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata(null));
public ImageSource NormalImage
{
get { return (ImageSource)GetValue(NormalImageProperty); }
set { SetValue(NormalImageProperty, value); }
}
public static readonly DependencyProperty NormalImageProperty =
DependencyProperty.Register("NormalImage", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata(null));
public event RoutedEventHandler Click;
public ImageButton()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
if (Click != null)
{
Click(this, e);
}
}
}
}
Example usage:
<local:ImageButton x:Name="imgbutton"
NormalImage="C:/1.png"
DisabledImage="C:/2.png"
Click="ImgButton_Click"/>
(Note that the current namespace is Test
, you might want to change that; Also i set a fixed size on the internal button, which you might want to remove, just make sure to set the size somewhere since i think it will not use any space at all if you don't.)
This is how I see it:
1) Create your MyImageButton
class which should inherit regular Button
and include two dependency properties - NormalImage
and DisabledImage
. These properties should be of ImageSource
type. See here how to define dependency properties: http://msdn.microsoft.com/en-us/library/ms752914.aspx#back_dependency_properties
2) Change your style to be a style for MyImageButton
:
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type MyControls:MyImageButton}">
3) Change ImageBrush
in your style for both enabled and disabled mode to use TemplateBinding
. This is how it should be for enabled mode:
<ImageBrush ImageSource="{TemplateBinding NormalImage}" />
Take a look at greyableimage.codeplex.com
This can be used in place of a regular image control on buttons, menus, toolbars etc. It auto-generates a "greyed-out" version of the content that will be displayed when the parent control is disabled.
精彩评论