介绍
本文以前面的文章(中介绍的概念部分和第二部分)创建一个使用彩色图像切换按钮。
ImageToggleButton
而不是从继承的切换按钮
,我们继承ContentControl中
和手动执行切换功能。像ColorImage
和ImageButton的
前面的文章中介绍,ImageToggleButton
定义以同样的方式在图像的属性。
用法示例
<Controls:ImageToggleButton Source="YourImageSource" ImageWidth="30" ImageHeight="20" Text="" CheckedToolTip="I'm checked right now..." UncheckedToolTip="I'm unchecked right now..." IsChecked="{Binding SomeBooleanVar}" GroupName="First Group"/>
请注意以下特性:
-
文本
- 显示的文本旁边的按钮
-
CheckedToolTip
- 当按钮被选中来显示尖
-
UncheckedToolTip
- 如果未选中的按钮显示的提示
-
组名
-
允许分组多个按钮像
单选
和只确保一个组中在任何给定时间检查
-
允许分组多个按钮像
ImageToggleButton.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Controls
{
public class ImageToggleButton : ContentControl
{
public event EventHandler<CheckedEventArgs> Checked;
public event EventHandler<EventArgs> Click;
#region DependencyProperties
public static DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(ImageSource), typeof(ImageToggleButton),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnSourceChanged));
public ImageSource Source
{
get
{
return (ImageSource)GetValue(SourceProperty);
}
set
{
SetValue(SourceProperty, value);
}
}
private static void OnSourceChanged
(DependencyObject Object, DependencyPropertyChangedEventArgs e)
{
ImageToggleButton ImageToggleButton = Object as ImageToggleButton;
ImageToggleButton.ImageBrush = new ImageBrush(ImageToggleButton.Source);
}
public static DependencyProperty ImageBrushProperty =
DependencyProperty.Register("ImageBrush", typeof(ImageBrush),
typeof(ImageToggleButton), new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public ImageBrush ImageBrush
{
get
{
return (ImageBrush)GetValue(ImageBrushProperty);
}
set
{
SetValue(ImageBrushProperty, value);
}
}
public static readonly DependencyProperty ImageColorProperty =
DependencyProperty.Register("ImageColor", typeof(Brush), typeof(ImageToggleButton),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public Brush ImageColor
{
get
{
return (Brush)GetValue(ImageColorProperty);
}
set
{
SetValue(ImageColorProperty, value);
}
}
public static DependencyProperty IsCheckedProperty =
DependencyProperty.Register("IsChecked", typeof(bool), typeof(ImageToggleButton),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnIsCheckedChanged));
public bool IsChecked
{
get
{
return (bool)GetValue(IsCheckedProperty);
}
set
{
SetValue(IsCheckedProperty, value);
}
}
private static void OnIsCheckedChanged(DependencyObject Object,
DependencyPropertyChangedEventArgs e)
{
ImageToggleButton ImageToggleButton = Object as ImageToggleButton;
if (ImageToggleButton.IsChecked && ImageToggleButton.Checked != null)
ImageToggleButton.Checked(ImageToggleButton,
new CheckedEventArgs(ImageToggleButton.IsChecked));
}
public static DependencyProperty GroupNameProperty = DependencyProperty.Register
("GroupName", typeof(string), typeof(ImageToggleButton),
new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnGroupNameChanged));
public string GroupName
{
get
{
return (string)GetValue(GroupNameProperty);
}
set
{
SetValue(GroupNameProperty, value);
}
}
private static void OnGroupNameChanged(DependencyObject Object,
DependencyPropertyChangedEventArgs e)
{
ImageToggleButton ImageToggleButton = Object as ImageToggleButton;
if (ImageToggleButton.GroupName == string.Empty)
{
ImageToggleButton.Checked -= ImageToggleButton.ImageToggleButton_Checked;
} else
{
ImageToggleButton.Checked += ImageToggleButton.ImageToggleButton_Checked;
}
}
private void ImageToggleButton_Checked(object sender, CheckedEventArgs e)
{
//We only want to affect the other values if current is true.
//This avoids other controls from attempting to execute same method when their values
//have changed.
if (e.NewValue)
{
//In order for this to work, all controls sharing same group name
//should be in same parent.
DependencyObject Parent = this.FindParent<DependencyObject>(this);
for (int i = 0, Count = VisualTreeHelper.GetChildrenCount(Parent); i < Count; i++)
{
var Child = VisualTreeHelper.GetChild(Parent, i);
if (!(Child is ImageToggleButton)) continue; //If it's not same type
//of control, skip it
ImageToggleButton Button = Child as ImageToggleButton;
if (Button == this) continue; //If we're at this, skip it
Button.IsChecked = false; //If it's not this, we'll want to uncheck it.
}
}
}
public static DependencyProperty CheckedToolTipProperty =
DependencyProperty.Register("CheckedToolTip", typeof(string),
typeof(ImageToggleButton), new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string CheckedToolTip
{
get
{
return (string)GetValue(CheckedToolTipProperty);
}
set
{
SetValue(CheckedToolTipProperty, value);
}
}
public static DependencyProperty UncheckedToolTipProperty =
DependencyProperty.Register("UncheckedToolTip", typeof(string),
typeof(ImageToggleButton), new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string UncheckedToolTip
{
get
{
return (string)GetValue(UncheckedToolTipProperty);
}
set
{
SetValue(UncheckedToolTipProperty, value);
}
}
public static DependencyProperty ImageWidthProperty =
DependencyProperty.Register("ImageWidth", typeof(double), typeof(ImageToggleButton),
new FrameworkPropertyMetadata(16.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public double ImageWidth
{
get
{
return (double)GetValue(ImageWidthProperty);
}
set
{
SetValue(ImageWidthProperty, value);
}
}
public static DependencyProperty ImageHeightProperty =
DependencyProperty.Register("ImageHeight", typeof(double), typeof(ImageToggleButton),
new FrameworkPropertyMetadata(16.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public double ImageHeight
{
get
{
return (double)GetValue(ImageHeightProperty);
}
set
{
SetValue(ImageHeightProperty, value);
}
}
public static DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(object), typeof(ImageToggleButton),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public object Text
{
get
{
return (object)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
#endregion
#region Methods
private T FindParent<T>(DependencyObject child) where T : DependencyObject
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child); //Get parent item
if (parentObject == null) return null; //We've reached the end of the tree
T parent = parentObject as T; //Check if the parent matches the type we're looking for
if (parent != null) return parent; else return FindParent<T>(parentObject);
}
public void SetGroup()
{
}
#endregion
#region Override Methods
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
this.IsChecked = this.IsChecked false : true;
if (this.Click != null) this.Click(this, new EventArgs());
}
#endregion
#region ImageToggleButton
public ImageToggleButton()
{
this.DefaultStyleKey = typeof(ImageToggleButton);
}
public override void OnApplyTemplate()
{
base.ApplyTemplate();
}
#endregion
}
}
/Themes/Generic.xaml
<Style x:Key="{x:Type Controls:ImageToggleButton}" TargetType="{x:Type Controls:ImageToggleButton}">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ImageToggleButton}">
<Border Margin="{TemplateBinding Margin}" Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Controls:ColorImage
x:Name="PART_Rectangle"
Source="{TemplateBinding Source}"
ImageWidth="{TemplateBinding ImageWidth}"
ImageHeight="{TemplateBinding ImageHeight}"
ImageColor="{TemplateBinding ImageColor}"
VerticalAlignment="Center"/>
<Label
Grid.Column="1"
Content="{TemplateBinding Text}"
Margin="10,0,0,0"
VerticalAlignment="Center"
Visibility="{TemplateBinding Text,
Converter={StaticResource NullObjectToVisibilityConverter}}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="ImageColor" Value="{DynamicResource ImageHoverBackground}"/>
<Setter Property="ToolTip" Value="{Binding CheckedToolTip,
RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="ImageColor" Value="{DynamicResource ImageBackground}"/>
<Setter Property="ToolTip" Value="{Binding UncheckedToolTip,
RelativeSource={RelativeSource Self}}"/>
</Trigger>
</Style.Triggers>
</Style>
NullObjectToVisibilityConverter.cs
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace Data
{
[ValueConversion(typeof(object), typeof(Visibility))]
public class NullObjectToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}