在实际工作中,面对不同的客户需求,需要让空间显示出不同的效果。当style已经不能足够满足客户需求时,就需要程序猿自己设计自定义控件了。

根据工作经历,LZ做了个关于自定义控件的小Demo,仅供参考。

实现操作分为三部分,话不多说,直接上代码。

一.控件后台设置

public class ImageButton : Button
{
public ImageButton() {
this.PreviewMouseDown += ImageButton_PreviewMouseDown;
this.PreviewMouseUp += ImageButton_PreviewMouseUp;
} void ImageButton_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("");
} void ImageButton_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show(""); } public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
} public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata(null));
}

根据控件需求对这个类做不同的继承,LZ做的控件是Button,所以继承自Button。
然后对ImageSource对应下文的Binding,做依赖属性。

this.PreviewMouseDown+=PreviewMouseDown;是对Button本身的响应事件做绑定。

二.控件界面设定

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:helper="clr-namespace:DemoZDY">
<Style TargetType="{x:Type helper:ImageButton}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Cursor" Value="Hand" />
<Setter Property="FontFamily" Value="微软雅黑" />
<Setter Property="FontSize" Value=""/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type helper:ImageButton}">
<StackPanel>
<Image Name="Image" Stretch="Fill" Source="{TemplateBinding ImageSource}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

控件内容比较简单,上面一个图片,下面一个Text内容。

Helper是指(一)中的命名空间。

三.MainWindow界面

<Window x:Class="DemoZDY.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="" Width=""
xmlns:helper="clr-namespace:DemoZDY">
<StackPanel>
<helper:ImageButton ImageSource="Status-False.png" Width="" Content="Click"/>
</StackPanel>
</Window>

简单一个自定义控件完成。但该控件不是很具体,下面再写一个稍微复杂点的自定义Buton控件。

四.新自定义button

  控件界面差别不大,主要是后台代码和使用的图片资源不同。

  (1)图片

点击效果:正常状态下显示上半部分,在被点击时显示下半部分,点击后恢复上半部分。

  (2)控件后台代码

 [TemplatePart(Name = "PART_Image", Type = typeof(Image))]
public class HoverButton : Button
{
private void OnImageSourceChanged(ImageSource oldValue, ImageSource newValue)
{
if (newValue is BitmapSource)
{
int w = (int)(newValue.Width);
int h = (int)(newValue.Height / ); NormalImage = new CroppedBitmap(newValue as BitmapSource, new Int32Rect(, , w, h));
PressedImage = new CroppedBitmap(newValue as BitmapSource, new Int32Rect(, h, w, h));
}
} public HoverButton()
{
this.PreviewMouseDown += OnPreviewMouseDown;
this.PreviewMouseUp += OnPreviewMouseUp;
} private void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (image != null)
{
image.Source = PressedImage;
this.CaptureMouse();
}
//e.Handled = true;
} private void OnPreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (image != null)
{
if (this.IsMouseCaptured)
{
this.ReleaseMouseCapture();
} image.Source = NormalImage;
this.OnClick();
}
//e.Handled = true;
} public override void OnApplyTemplate()
{
base.OnApplyTemplate();
image = this.GetTemplateChild("PART_Image") as Image;
} public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
} public ImageSource NormalImage
{
get { return (ImageSource)GetValue(NormalImageProperty); }
set { SetValue(NormalImageProperty, value); }
} public ImageSource PressedImage
{
get { return (ImageSource)GetValue(PressedImageProperty); }
set { SetValue(PressedImageProperty, value); }
} public static void OnImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as HoverButton).OnImageSourceChanged(e.OldValue as ImageSource, e.NewValue as ImageSource);
} static HoverButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(HoverButton), new FrameworkPropertyMetadata(typeof(HoverButton)));
} public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(HoverButton), new UIPropertyMetadata(null, OnImageSourceChanged)); public static readonly DependencyProperty NormalImageProperty =
DependencyProperty.Register("NormalImage", typeof(ImageSource), typeof(HoverButton), new UIPropertyMetadata(null)); public static readonly DependencyProperty PressedImageProperty =
DependencyProperty.Register("PressedImage", typeof(ImageSource), typeof(HoverButton), new UIPropertyMetadata(null)); public Image image;
}
  • [TemplatePart(Name = "PART_Image", Type = typeof(Image))],是一种契约,意思是告诉要来写ControlTemplate的用户 , 你的ControlTemplate中需要有一个x:Name为“PART_Image” , 类型为Image, 当然这个类型可以是继承来的, 为什么一定要包含这些契约规定的元素 , 因为逻辑部分对这些东西进行了引用,它们将对控件的默认行为起着关键作用, 可以理解为这个控件的最基本元素 , 是实现默认行为的最小集合, 自然,你的ControlTemplate中如果没有包含契约中的内容 , 则相应的逻辑将无法实现。
  • OnImageSourceChanged里意思是将图片分为上下两部分(NormalImage和PressedImage)
  • CaptureMouse和ReleaseMouseCapture是指光标的捕获和释放。
  • OnApplyTemplate 显示由自定义控件定义的 OnApplyTemplate 重写,设计该自定义控件是因为考虑到调用方可能通过模板和样式系统来定义和应用自己的控件模板。  作为其定义的一部分,模板中命名元素的控件属性是必需的,如 UpButtonElement。  然后 OnApplyTemplate 在加载模板时基于此命名协定检索对象引用。  此外,此示例还调用专用方法 UpdateState(未显示定义)。  这是 OnApplyTemplate 的另一个常见方案:确保为控件的起始状态设置可视状态,在此例中,通过调用专用方法来确保,该专用方法考虑了控件的所有已定义状态并调用 GoToState 来设置适当的状态。 (msdn.microsoft.com中的定义)
  • 其他的都很简单,切记要依赖属性。

五.Demo下载

WPF 自定义控件的更多相关文章

  1. WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展

    一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要是对文本 ...

  2. WPF自定义控件与样式(1)-矢量字体图标(iconfont)

    一.图标字体 图标字体在网页开发上运用非常广泛,具体可以网络搜索了解,网页上的运用有很多例子,如Bootstrap.但在C/S程序中使用还不多,字体图标其实就是把矢量图形打包到字体文件里,就像使用一般 ...

  3. WPF自定义控件与样式(2)-自定义按钮FButton

    一.前言.效果图 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 还是先看看效果 ...

  4. WPF自定义控件与样式(15)-终结篇 & 系列文章索引 & 源码共享

    系列文章目录  WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与样式(3)-TextBox & Ric ...

  5. WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Che ...

  6. WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 日历控 ...

  7. WPF自定义控件与样式(6)-ScrollViewer与ListBox自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Scr ...

  8. WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Dat ...

  9. WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...

  10. WPF自定义控件与样式(9)-树控件TreeView与菜单Menu-ContextMenu

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 菜单M ...

随机推荐

  1. C#中using关键字的作用及用法

    using的用途和使用技巧. 1.  引用命名空间 2.  为命名空间或类型创建别名 3.  使用using语句 1.  引用命名空间,这样可以在程序中引用命名空间的类型而不必指定详细的命名空间. a ...

  2. leetcde37. Sudoku Solver

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

  3. 将Rmarkdown文件转为pdf文件

    knitr包只能够将R markdown文件转为html格式,若想要将其转化为pdf格式,还要安装另一个包 # Install and load package install.packages(&q ...

  4. 我的Java后端书架 (2016年暮春3.0版)

      04月 24, 2016 | Filed under 技术 http://calvin1978.blogcn.com/articles/javabookshelf.html 书架主要针对Java后 ...

  5. 对弈类游戏的人工智能(5)--2048游戏AI的解读

    前言: 闲得没事, 网上搜"游戏AI", 看到一篇<<2048游戏的最佳算法是?来看看AI版作者的回答>>的文章. 而这篇文章刚好和之前讲的对弈类游戏AI对 ...

  6. Node.js高级编程读书笔记 - 5 数据库 - Never

    Outline 6 连接数据库 6.1 使用node-mysql连接MySQL数据库 6.2 使用Nano连接CouchDB数据库 6.3 使用Mongoose连接MongoDB数据库 6 连接数据库 ...

  7. CE5 中断

    一.intr.h里面定义硬件中断号 #define IRQ_EINT0 0 #define IRQ_EINT1 1 #define IRQ_EINT2 2 #define IRQ_EINT3 3 #d ...

  8. 论文笔记之:Generative Adversarial Text to Image Synthesis

    Generative Adversarial Text to Image Synthesis ICML 2016  摘要:本文将文本和图像练习起来,根据文本生成图像,结合 CNN 和 GAN 来有效的 ...

  9. 12 factor 目录

    I. 基准代码 一份基准代码,多份部署 II. 依赖 显式声明依赖关系 III. 配置 在环境中存储配置 IV. 后端服务 把后端服务当作附加资源 V. 构建,发布,运行 严格分离构建和运行 VI. ...

  10. centos中开机时如何自启动samba服务器

    解决办法如下:1.编辑rc.local文件#vi /etc/rc.d/rc.local2.加入如下启动命令/usr/sbin/apachectl start/etc/rc.d/init.d/mysql ...