自己写一个图片按钮(XAML)

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

每次都修改按钮的样式来实现这个做法,既麻烦又会生成大段的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. 把这三个属性设置三张合适的图片,图片按钮即可使用。

时间: 2024-10-11 07:54:10

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

android写一个图片选择

可以达到的效果 第一个图片的位置放照相机,点击打开照相机 其余的是显示全部存储的图片,点击一次是查看大图,长按则是每张图片出现一个checkBox,可以进行选择 下面是实例效果图 MainActivity 类 public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener, ImageAdapter

自己写一个图片验证码程序

本程序基于struts2,用action响应请求. 一.首先,创建一个用于产生随即验证码图片的类ImageCode.java. 1 package com.exp.image; 2 3 import java.awt.BasicStroke; 4 import java.awt.Color; 5 import java.awt.Font; 6 import java.awt.Graphics; 7 import java.awt.Graphics2D; 8 import java.awt.Ren

写一个图片轮播器(使用collectionView)

一.属性 我们需要一个 collectionView 和一个 NStimer .collectionView 用来存放需要循环播放的对象, NSTimer 用来定时滚动collectionView @interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource> @property(nonatomic,strong)UICollectionView* showCollection; @proper

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

1.先看效果: 熟悉的图片轮播,只要是个网站,百分之90以上会有个图片轮播.我认为使用图片轮播. 第一可以给人以一种美观的感受,而不会显得网站那么呆板, 第二可以增加显示内容,同样的区域可以显示更多内容. 2.每学一个新东西 ,图片轮播都是很好的练手案例,而且,也很实用. 3.基本要求:页面加载,自动播放.鼠标悬停,停止播放.鼠标离开,继续播放 点击左右箭头切换上一张,下一张图片. 下方小圆点显示当前位第几张图片. 4.使用Vue实现,想法: 5.示例代码 结构html: <template>

用extjs6.0写一个系统登录及注销

本文基于ext-6.0.0 一.用sencha cmd建立一个ExtJs小项目 首先,需要一个命令行工具.进入extjs所在目录. 然后,输入:sencha -sdk [ExtJs6.0文件夹地址] generate app [项目名称] [项目路径] 例如:sencha -sdk ext-6.0.0 generate app App MyApp (注):还可以加--classic或--modern建立pc或WAP单独项目 二.在浏览器打开 命令行输入:sencha app watch 三.开始

NGUI 3.5教程(四)Atlas和Sprite(制作图片按钮)

向原创致敬http://blog.csdn.net/chenggong2dm/article/details/25594059 Atlas是NGUI的图集.我的理解是:Atlas把你的一些零散的图片,合并成一张图.这样做的好处是,可以降低Draw Call.我不了解它的底层运作机制,我猜应该也是再行进DXT之类的纹理压缩,所以,最好把图集的尺寸,也做成128, 256,512,1024之类的大小,以方便其进行格式压缩. 概念: Atlas : 图集.把美术给你提供的素材,用 NGUI 的 Atl

用 EPWA 写一个 漫画阅读器 ComicReader

用 EPWA 写一个 图片播放器 ComicReader . 有关 EPWA,见 <我发起并创立了一个 EPWA 的 开源项目> https://www.cnblogs.com/KSongKing/p/10745935.html , js 库 用的是 jWebForm, 见 <我发起并创立了一个 Javascript 前端库 开源项目 jWebForm> https://www.cnblogs.com/KSongKing/p/10326119.html , ComicReader 

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

根据记忆中eoe的Intent相关视频,模仿,写一个打开图片的Activity 1.在主Activity的button时间中,通过设置action.category.data打开一个图片.这时代码已经可以运行,将使用系统默认的工具打开图片. Intent intentImage = new Intent(Intent.ACTION_VIEW); intentImage.addCategory(Intent.CATEGORY_DEFAULT); File file = new File("/sto

如何写一个发微博的页面(包括插入图片,插入表情,插入话题,插入Location) (一)

先上效果图: 先看页面布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"