有时需要用三张图片(正常状态,鼠标移上,鼠标按下)来作为一个按钮的样式,虽然这种做法不好,应该用矢量的方式制作样式,但有的时候还是需要这样做的。

每次都修改按钮的样式来实现这个做法,既麻烦又会生成大段的XAML代码,不利于维护,抽出一个自定义图片按钮控件,只需传入三张图片的路径即可使用,显然是更好的做法,下面就演示一下如何编写这个控件,VS2015和Blend2015结合使用。

1. 首先,在VS中新建一个WPF自定义控件库,命名为WpfCustomControlLibrary,系统会自动生成一个CustomControl1类,并生成一个Themes文件夹,其中包含一个资源字典文件Generic.xaml。如果打开AssemblyInfo.cs文件,会看到包含如下代码,

[assembly:ThemeInfo(
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
//(在页面、应用程序或任何主题特定资源词典中
// 未找到某个资源的情况下使用)
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
//(在页面、应用程序或任何主题特定资源词典中
// 未找到某个资源的情况下使用)
)]

这段代码指明在Themes文件夹下的Generic.xaml资源字典中包含控件的默认样式,这正是WPF自定义控件库和一般程序集的区别。

2. 将CustomControl1类改为ImageButton

此时的初始代码如下,

    public class ImageButton : Control
{
static ImageButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton)));
}
}
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomControlLibrary">
<Style TargetType="{x:Type local:ImageButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ImageButton}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

3. 把ImageButton的基类改为Button。

4. 在ImageButton中加入三个依赖属性,如下

        public static readonly DependencyProperty NormalImageProperty =
DependencyProperty.RegisterAttached("NormalImage", typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(null)); public ImageSource NormalImage
{
get { return (ImageSource)GetValue(NormalImageProperty); }
set { SetValue(NormalImageProperty, value); }
} public static readonly DependencyProperty MouseOverImageProperty =
DependencyProperty.RegisterAttached("MouseOverImage", typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(null)); public ImageSource MouseOverImage
{
get { return (ImageSource)GetValue(MouseOverImageProperty); }
set { SetValue(MouseOverImageProperty, value); }
} public static readonly DependencyProperty PressedImageProperty =
DependencyProperty.RegisterAttached("PressedImage", typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(null)); public ImageSource PressedImage
{
get { return (ImageSource)GetValue(PressedImageProperty); }
set { SetValue(PressedImageProperty, value); }
}

5. 新建一个WPF应用程序项目引用该自定义控件库,在一个页面中,加入ImageButton控件。选中ImageButton控件,点击美工板导航栏中的[ImageButton],在弹出的菜单中选择编辑模板-编辑副本,在弹出的对话框中输入ImageButtonStyle,选择该文档,点击确定。

6. 在模板编辑状态下,右键点击文档大纲面板中的[Border],选择更改布局类型-Grid,然后将Grid的背景清空。向Grid中加入三个Image控件,并重置布局。可从资产面板加入,可在资产面板的搜索栏中输入Image查找。将三个Image的Width和Height清空,将Stretch属性改为None。

7. 将三个Image的Source属性从上到下分别改为模板绑定NormalImage,PressedImage和MouseOverImage,修改方法为在属性面板中点击Source属性右边的小方块,选择模板绑定-NormalImage。把PressedImage和MouseOverImage的Image的Visibility属性改为Collapsed。

8. 在状态面板中,点击MouseOver,在文档大纲面板中,选择第一个Image控件,在属性面板中,将Visibility属性改为Collapsed。选择第三个也就是MouseOverImage的Image控件,在属性面板中,将Visibility属性改为Visible。

在状态面板中,点击Pressed,在文档大纲面板中,选择第一个Image控件,在属性面板中,将Visibility属性改为Collapsed。选择第二个也就是PressedImage的Image控件,在属性面板中,将Visibility属性改为Visible。

此时ImageButtonStyle的代码如下,

<Style TargetType="{x:Type local:ImageButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ImageButton}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image1">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image2">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image x:Name="image" Source="{TemplateBinding NormalImage}" Stretch="None"/>
<Image x:Name="image2" Source="{TemplateBinding PressedImage}" Stretch="None" Visibility="Collapsed"/>
<Image x:Name="image1" Source="{TemplateBinding MouseOverImage}" Stretch="None" Visibility="Collapsed"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

9. 用这个Style中的ControlTemple部分替换自定义控件库中的Themes文件夹下的Generic.xaml文件中的ImageButton样式的ControlTemple部分。注意修改TargetType为{x:Type local:ImageButton}"。

10. 这时图片按钮控件已经完成了,在WPF应用程序项目中的一个页面上,从资产面板中加入ImageButton控件(选择项目分类)。选择ImageButton控件,在属性面板中可以看到,在杂项组下,存在NormalImage,MouseOverImage和PressedImage三个属性,可分别设置图片。

11. 把这三个属性设置三张合适的图片,图片按钮即可使用。

自己写一个图片按钮(XAML)的更多相关文章

  1. 用 EPWA 写一个 图片播放器 PicturePlayer

    用 EPWA 写一个 图片播放器  PicturePlayer  . 有关 EPWA,见 <我发起并创立了一个 EPWA 的 开源项目>   https://www.cnblogs.com ...

  2. [jQuery插件]手写一个图片懒加载实现

    教你做图片懒加载插件 那一年 那一年,我还年轻 刚接手一个ASP.NET MVC 的 web 项目, (C#/jQuery/Bootstrap) 并没有做 web 的经验,没有预留学习时间, (作为项 ...

  3. Vue学习—Vue写一个图片轮播组件

    1.先看效果: 熟悉的图片轮播,只要是个网站,百分之90以上会有个图片轮播.我认为使用图片轮播. 第一可以给人以一种美观的感受,而不会显得网站那么呆板, 第二可以增加显示内容,同样的区域可以显示更多内 ...

  4. javascript小记五则:用JS写一个图片左右自由滚动的“跑马灯”效果

    之前看了很多百度搜索出的东西,十个有九个是不能实用的,个个讲的都不详细,今天详细给大家讲解下关于这个图片“跑马灯”滚动效果,源码如下: <!DOCTYPE html PUBLIC "- ...

  5. Extjs6(二)——用extjs6.0写一个系统登录及注销

    本文基于ext-6.0.0 一.写login页 1.在view文件夹中创建login文件夹,在login中创建文件login.js和loginController.js(login.js放在class ...

  6. 跟我一起用Symfony写一个博客网站;

    我的微信公众号感兴趣的话可以扫一下, 或者加微信号   whenDreams 第一部分:基础设置,跑起一个页面-首页 第一步: composer create-project symfony/fram ...

  7. Expression Blend4经验分享:制作一个简单的图片按钮样式

    这次分享如何做一个简单的图片按钮经验 在我的个人Silverlight网页上,有个Iphone手机的效果,其中用到大量的图片按钮 http://raimon.6.gwidc.com/Iphone/de ...

  8. Android 自己写一个打开图片的Activity

    根据记忆中eoe的Intent相关视频,模仿,写一个打开图片的Activity 1.在主Activity的button时间中,通过设置action.category.data打开一个图片.这时代码已经 ...

  9. 设置一个按钮为一个图片,不要border

    //设置一个按钮为一个图片,不要border ImageIcon searchIcon = ImageToolkit.loadImageIcon(/search.png"); ImageIc ...

随机推荐

  1. 学习笔记之SQL / MySQL

    SQL Fiddle(在线执行SQL语句的网站) http://www.sqlfiddle.com/ MySQL https://www.mysql.com/ MySQL :: MySQL 5.7 R ...

  2. c语言个人财务管理系统

    这个是我的一个网上朋友写的,仅供大家参考: 在这里留个记录 #include<stdio.h>#include<string.h>#define null 0#define m ...

  3. window server2008 r2 限制远程访问用户数量

    在服务器端设置 修改组策略 1,开始-运行-gpedit.msc-计算机配置-管理模板-Windows组件-远程桌面服务-远程桌面会话主机-限制连接数量-开启并改为1

  4. 使用protocol buffer时关闭警告

    在生成的文件头尾添加屏蔽警告的代码. 头部: #pragma warning(push, 2) // --------------------------------------------- 尾部: ...

  5. Hyberledger-Fabric 1.00 RPC学习(2)尝试建立一个network

    本文参考:http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html 这里我们学习建立第一个Hyperledger Fa ...

  6. C++指针的长度

    每台计算机都有字长,指明指针数据的标称大小----来自深入理解计算机系统 每台计算机的字长指明了它的虚拟空间大小.比如32位的机器,虚拟空间地址为0~2^w-1程序最多访问2^w个字节 对于32位程序 ...

  7. Shell 函数库

    1.为什么要定义函数库 经常使用的重复代码封装成函数文件 一般不直接执行,而是由其他脚本调用 2.编写一个函数库,该函数库实现以下几个函数. 1.加法函数:add 2.减法函数:reduce 3.乘法 ...

  8. 普通方法调用,Invoke,begininvoke三者的区别总结及异步与同步的区别总结

    (1)普通方法调用(直接调用)与Invoke()方法调用方法 使用的线程Id是一样的 即属于同步. (2)BeginInvoke(<输入和输出变量>,AsyncCallback callb ...

  9. 使用TensorFlow识别照片中的物体

    1.环境ubuntu14.04.5 安装TensorFlow 官方文档:https://www.tensorflow.org/install/install_linux sudo pip instal ...

  10. 提交iframe页面中的表单

    function getIframeDoc(id){             var doc;            if (document.all){//IE                 do ...