在实际工作中,面对不同的客户需求,需要让空间显示出不同的效果。当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. vim使用过程

    首先推荐几篇文章先: 用Vim编程——配置与技巧 有时候需要设置映射键,此时可以在.vimrc中配置一些项就可以轻松映射了. 以下是几个映射模式: map : 正常模式,可视化模式和运算符模式可用 n ...

  2. C++模板中的函数对象

    在C++模板类map中一个参数为Compare类型,该类型为一个比较函数,其完整定义如下: template< class Key, class T, class Compare = std:: ...

  3. setImageBitmap和setImageResource

    同样的布局文件,小分辨率手机: 1.使用setImageBitmap设置时,出现如下现象:  2.使用setImageResource时,图片显示正常 原因: setImageResource(id) ...

  4. python数据结构与算法——队列

    队列结构可以使用数组来模拟,只需要设定头和尾的两个标记 参考自<啊哈> # 按书中的代码会出现索引越界的问题(书中申请了超量的空间) # 尝试令tai初始为len(q)-1则不会出错但少了 ...

  5. C++ Pirmer : 第十五章 : 面向对象程序设计之基类和派生的定义、类型转换与继承与虚函数

    基类和派生类的定义以及虚函数 基类Quote的定义: classs Quote { public: Quote() = default; Quote(cosnt std::string& bo ...

  6. 第七课第六节,T语言流程语句( 版本5.0)

    select语句 seelct语句,可以说是if语句的升级版,当我们的if语句嵌套太多,或者if语句判断太多的时候,都可以考虑使用选择语句 在多条件判断的时候,选择语句的执行速度比多个if语句要快而且 ...

  7. Codeforces Round #162 (Div. 2)

    A. Colorful Stones (Simplified Edition) 模拟. B. Roadside Trees (Simplified Edition) 每次转移时,只需要爬到\(min( ...

  8. main函数的简介

    ////  main函数的简介.h//  IOS笔记////  Created by .//  Copyright © 2015年  All rights reserved.// //#import ...

  9. 转载-- http接口、api接口、RPC接口、RMI、webservice、Restful等概念

     http接口.api接口.RPC接口.RMI.webservice.Restful等概念 收藏 Linux一叶 https://my.oschina.net/heavenly/blog/499661 ...

  10. 简单的鼠标可拖动div 兼容IE/FF

    来源:http://www.cnblogs.com/imwtr/p/4355416.html 作者: 主要思路: 一个div,注册监听onmousedown事件,然后处理获取的对象及其相关值(对象高度 ...