接触WPF也有两个多月了,有了一定的理论基础和项目经验,现在打算写一个系列,做出来一个WPF的控件库。一方面可以加强自己的水平,另一方面可以给正在学习WPF的同行一个参考。本人水平有限,难免有一些错误,望各位指出!
先上图看看各种效果:
这个Button是我继承系统Button后扩展的,主要实现了:可设置悬浮和按下时的背景,可改变形状,并可设置按钮按下后保持锁定状态等功能。
这个Button我命名为XButton,扩展的所有属性我都会以X开头命名。好了,具体的东西看代码吧!
先来Xaml的:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:KAN.WPF.XCtrl.Controls">
<Style x:Key="{x:Type ctrl:XButton}" TargetType="{x:Type ctrl:XButton}">
<Style.Resources>
<ResourceDictionary Source="/KAN.WPF.Xctrl;component/Themes/CommonStyle.xaml"/>
</Style.Resources>
<Setter Property="FocusVisualStyle" Value="{StaticResource StyleFocusVisual}"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="Silver"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ctrl:XButton}">
<!--定义视觉树-->
<Grid>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<!--这里的Path就是用来实现各种外形的-->
<Path x:Name="bdrButton"
Data="{Binding XShape, RelativeSource={RelativeSource TemplatedParent}}"
Stroke="{Binding XStrokeBrush, RelativeSource={RelativeSource TemplatedParent}}"
StrokeThickness="{Binding XStrokeThickness, RelativeSource={RelativeSource TemplatedParent}}"
Stretch="Fill" RenderTransformOrigin="0.5,0.5" Fill="{TemplateBinding Control.Background}">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Border>
<ContentPresenter Name="contentPresenter" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Focusable="False" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" Content="{TemplateBinding ContentControl.Content}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<!--设置触发器-->
<ControlTemplate.Triggers>
<!--鼠标移动上去时-->
<Trigger Property="UIElement.IsMouseOver" Value="True" >
<Setter TargetName="bdrButton" Value="{Binding XMoverBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
</Trigger>
<!--鼠标按下去时-->
<Trigger Property="ButtonBase.IsPressed" Value="True">
<Setter TargetName="bdrButton" Value="{Binding XEnterBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
</Trigger>
<!--禁用Button时-->
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="bdrButton" Value="{Binding XUnEnabledBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
</Trigger>
<!--如果设置了锁住按下的状态的属性,那么当按下时-->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="True"/>
<Condition Property="XIsFoucedBrushLock" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="bdrButton" Value="{Binding XEnterBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
</MultiTrigger.Setters>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
其中的StyleFocusVisual是用来定义按Tab到这个控件上的样式的,代码如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="StyleFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border Margin="0" BorderBrush="#FF9FBDF4" BorderThickness="1"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
接下来是CS的:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Imaging; namespace KAN.WPF.XCtrl.Controls
{
/// <summary>
/// 扩展按钮:可设置悬浮和按下时的背景,可改变形状,并可设置按钮按下后保持锁定状态
/// </summary>
public class XButton : Button
{
#region 依赖属性
public static readonly DependencyProperty XMoverBrushProperty;//鼠标经过时的画刷
public static readonly DependencyProperty XEnterBrushProperty;//鼠标按下时的画刷
public static readonly DependencyProperty XUnEnabledBrushProperty;//禁用时的画刷
public static readonly DependencyProperty XIsFoucedBrushLockProperty;//是否得到焦点时锁住画刷
public static readonly DependencyProperty XShapeProperty;//外形的路径
public static readonly DependencyProperty XStrokeBrushProperty;//外形的路径着色
public static readonly DependencyProperty XStrokeThicknessProperty;//外形的路径粗细(默认为0,因为有Border边框,所以要设这个值,要先把BorderThickness设为0)
#endregion #region 内部方法
/// <summary>
/// 静态构造方法
/// </summary>
static XButton()
{
//注册依赖属性
XButton.XMoverBrushProperty = DependencyProperty.Register("XMoverBrush", typeof(Brush), typeof(XButton),
new PropertyMetadata(Brushes.WhiteSmoke));
XButton.XEnterBrushProperty = DependencyProperty.Register("XEnterBrush", typeof(Brush), typeof(XButton),
new PropertyMetadata(Brushes.Silver));
XButton.XUnEnabledBrushProperty = DependencyProperty.Register("XUnEnabledBrush", typeof(Brush), typeof(XButton),
new PropertyMetadata(Brushes.Silver));
XButton.XStrokeBrushProperty = DependencyProperty.Register("XStrokeBrush", typeof(Brush), typeof(XButton),
new PropertyMetadata(Brushes.Silver));
XButton.XStrokeThicknessProperty = DependencyProperty.Register("XStrokeThickness", typeof(Double), typeof(XButton),
new PropertyMetadata(0.0));
XButton.XIsFoucedBrushLockProperty = DependencyProperty.Register("XIsFoucedBrushLock", typeof(bool), typeof(XButton),
new PropertyMetadata(false));
XButton.XShapeProperty = DependencyProperty.Register("XShape", typeof(string), typeof(XButton),
new PropertyMetadata("M 0 0 L 0 0 L 100 0 L 100 100 L 0 100 Z"));
FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(XButton), new FrameworkPropertyMetadata(typeof(XButton)));
}
#endregion #region 公布属性
/// <summary>
/// 公布属性XMoverBrush(鼠标经过时的画刷)
/// </summary>
public Brush XMoverBrush
{
get
{
return base.GetValue(XButton.XMoverBrushProperty) as Brush;
}
set
{
base.SetValue(XButton.XMoverBrushProperty, value);
}
} /// <summary>
/// 公布属性XMoverBrush(鼠标按下时的画刷)
/// </summary>
public Brush XEnterBrush
{
get
{
return base.GetValue(XButton.XEnterBrushProperty) as Brush;
}
set
{
base.SetValue(XButton.XEnterBrushProperty, value);
}
} /// <summary>
/// 公布属性XUnEnabledBrush(禁用时的画刷)
/// </summary>
public Brush XUnEnabledBrush
{
get
{
return base.GetValue(XButton.XUnEnabledBrushProperty) as Brush;
}
set
{
base.SetValue(XButton.XUnEnabledBrushProperty, value);
}
} /// <summary>
/// 公布属性XIsFoucedBrushLock(是否得到焦点时锁住画刷)
/// </summary>
public bool XIsFoucedBrushLock
{
get
{
return (bool)base.GetValue(XButton.XIsFoucedBrushLockProperty);
}
set
{
base.SetValue(XButton.XIsFoucedBrushLockProperty, value);
}
} /// <summary>
/// 公布属性XShape(外形的路径)
/// </summary>
public String XShape
{
get
{
return base.GetValue(XButton.XShapeProperty) as String;
}
set
{
base.SetValue(XButton.XShapeProperty, value);
}
} /// <summary>
/// 公布属性XStrokeBrush(外形的路径着色)
/// </summary>
public Brush XStrokeBrush
{
get
{
return base.GetValue(XButton.XStrokeBrushProperty) as Brush;
}
set
{
base.SetValue(XButton.XStrokeBrushProperty, value);
}
} /// <summary>
/// 公布属性XStrokeThickness(外形的路径粗细)
/// </summary>
public Double XStrokeThickness
{
get
{
return (Double)base.GetValue(XButton.XStrokeThicknessProperty);
}
set
{
base.SetValue(XButton.XStrokeThicknessProperty, value);
}
}
#endregion
}
}
看了代码上的注释应该都能明白吧!要是有不明白的可以留言。
至于源代码,我之后会整理几个控件后一起发上来的!