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

每次都修改按钮的样式来实现这个做法,既麻烦又会生成大段的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. MySQL 多表关联更新及删除

    目录: <MySQL中的两种临时表> <MySQL 多表关联更新及删除> <mysql查询优化之三:查询优化器提示(hint)> 一.      多表关联更新 问题 ...

  2. 1711 Number Sequence(kmp)

    Number Sequence Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) To ...

  3. elasticsearch 官方入门 及 API

    https://www.elastic.co/guide/en/elasticsearch/reference/current/_basic_concepts.html 入门地址 ElasticSea ...

  4. 【转载】Python ConfigParser的使用

    1.基本的读取配置文件-read(filename) 直接读取ini文件内容-sections() 得到所有的section,并以列表的形式返回-options(section) 得到该section ...

  5. red ant

    Red Ant(红蚁)网络运维管理系统是IT运维管理系统,提供智能的B/S接口可视化人机界面,通过简单的操作实现全方位的网络专线.服务器.中间件.各种应 用程序.机房动力环境等监控管理,“化繁为简”, ...

  6. asp.net 不用控件,自动登录(用于和其他系统对接的时候,自动登录系统,用户体验好)

    if (System.Web.Security.Membership.ValidateUser("admin", "123456")) { //这句话很重要,他 ...

  7. less gradient-vertical 方法的实现

    // Vertical gradient using CSS where possible, and base64-encoded SVG for IE9 (enables use of this i ...

  8. Spring Cloud Bus实现自动更新配置

    一.概述 1. 配置环境 版本:Spring Boot版本2.0.3.RELEASE,Spring Cloud版本Finchley.SR1,RabbitMQ 3.7.7 说明:本文章是在https:/ ...

  9. php7源码编译安装

    以下以CentOS 7.2为例,安装php的运行环境,首先打开php官网http://php.net/点击导航栏的Downloads进入下载页面:http://php.net/downloads.ph ...

  10. 无法启动Tomcat, 端口被占用的问题

    这个错误是说这几个端口已经有某个应用程序占用了,所以Tomcat就没法启动了.   出现这个问题的原因可能有以下几种: 情况一:点击运行的时候没有选中页面或Servlet窗口的标签 标签被选中时: 标 ...