自定义控件之Button控件的自定义

第一步:编写自定义控件类

制作一个自定义的控件,首先要从编写控件的类开始。既然我们要做的是一个按钮控件,就让它继承自标准的Button控件,从而获得Button已实现的诸多功能(例如:Button 的 Click 事件)。

在Visual Studio里,创建(或打开)一个 Windows Phone 7 项目,添加一个类。代码如下:

public class ImageButton : Button

{

public static readonly DependencyProperty ImageSourceProperty =

DependencyProperty.Register(

"ImageSource",

typeof(ImageSource),

typeof(ImageButton),

null);



public ImageSource ImageSource

{

get { return (ImageSource)GetValue(ImageSourceProperty); }

set { SetValue(ImageSourceProperty, value); }

}

}

第二步:设计自定义控件的外观和行为

在Visual Studio里进行重新编译,好让刚刚声明的控件类生效。然后在 Expression Blend 中打开该项目。在 Expression Blend 界面左上角的 Assets 区域中,搜索 imagebutton 字样,可看到我们刚刚声明的 ImageButton 控件。

2.jpg

双击该控件,则在当前 page 中添加该控件。

3.jpg

至此,我们发现这个 ImageButton 控件的外观其实和标准的 Button 控件没有什么不同。这是由于我们尚未定义任何有关该控件的模板,因此系统就找到其基类的模板来进行显示。接下来,我们就生成并定义 ImageButton 的模板。

在选中 ImageButton 控件的状态下,于界面上方依次点击 [ImageButton] -> [Edit Template] -> [Edit a Copy...]。

4.jpg

扩展说明:

选择[Create Empty],则会生成一个空的模板。如果需要从头编写一个完全自定义的控件,可以选择此项。
选择[Edit a Copy...]意味着将当前控件的模板(如果不存在,则选择基类的模板)进行复制,并在此基础上进行修改。既然我们做的事情就是基于标准的 Button 控件进行扩展,因此该选项比较适合。

在弹出的对话框中,选择 [Apply to all] 和 [Application]。

<IGNORE_JS_OP>5.jpg

扩展说明:

当定义一个控件的模板时,可以选择给该模板指定一个关键字名称(key),那么在使用这样的模板时,就需要通过显示地(Explicitly) 指定其关键字来进行引用。而如果我们选择了 [Apply to all] 的方式,就意味着不给该模板指定任何关键字(key),那么这样的模板就是默 认模板(Implicit Style)。在一个应用程序范围内,针对同一种控件,只允许存在一个默认模板。
上述对话框中,[Define in] 区域用于指定模板的存放位置。如果选择了 [Application] 则该模板会被放置在当前项目中的 App.xaml 文件中,并且全局可见。通常,默认模板都应该放置于此。选择[This document] 则模板被放置在当前 page 文件中,且仅在当前页面有效。


点击确认,进入模板的编辑页面。

6.jpg

扩展说明:

在界面的左上方,选择 [States] 分页,可以看到一系列有关 Button 控件的 Visual State。(关于 Visual State 的介绍,请查看其他详细的资料)  
在 界面的左下方,可看到系统默认提供的 Button 控件的内部结构:一个Grid 控件内,嵌套一个名 为 [ButtonBackground] 的 Border 控件,其中又嵌套一个名 为 [ContentContainer] 的 ContentControl 控件。
究其原理,这 个 ContentControl 的 Content 属性(界面右下方红色圈圈)被绑定到了 Button 控件的 Content 属性上,于是我 们在使用 Button 控件时,无论在其 Content 属性上填写任何文字,或者放置任意图片,都能在 Button 控件的内容区域看到它们。


接下来,我们大刀阔斧地把模板中的 [ContentContainer] 及 [ButtonBackground] 都删除掉。在删除的过程中,Expression Blend 会提示说“由于删除了某些界面元素而影响了Visual State正常工作”,不必理会。最后只剩下 Grid 控件。

7.jpg

接下来我们给Grid中放置两个 Image 控件,这两个 Image 控件相互重叠。同时选中两个 Image 控件,然后点击 Margin 属性右侧的白色方块(Advanced options),然后选择重置(Reset),将所有 Margin 值清零。

8.jpg

仍然是在选中两个 Image 控件的状态下,点击 [Source] 属性右侧的浏览按钮,为其指定图片资源(最好是不超过200X200像素的 png 图片)。加载图片后,如果 Image 控件的大小发生明显的变化,则适当调整预览区下方的 [查看百分比] 来调整视野,但千万不要直接调整 Image 控件本身的 Width 及 Height。整个模板定义的过程中,这两个 Image 控件的 Width 及 Height 都应该显示 Auto (某数字) 。

9.jpg

提示:

在这一步骤中,之所以用“硬编码”的方式指定图片资源,仅仅是为了借助可视化的方式来进行模板编辑。待模板编辑完成之后,我们会把 Image 控件的图片资源绑定到我们在 ImageButton 类里声明的 ImageSource 变量。


接下来,给两个 Image 控件分别起名为 ImageBack 和 ImageFront(在 XAML 中,越是处在代码的上方,就意味着在运行时越在低层显示)。然后将 ImageBack 的透明度(Opacity)设置为 0%,让它默认不可见。

10.jpg

在界面左上区域的 [States] 分页中,选择 [CommonStates] 下的 [Pressed] 状态(Visual State)。然后选择 ImageFront 控件,将其大小(Sacle)的 X 及 Y 值设置为 0.8,并将其透明度设置为 50%。这一步操作,是定义按钮在被按下的时候,其外观应发生的变化。

11.jpg

依然是在 [Pressed] 状态的编辑模式下,选择 ImageBack 控件。 然后点击 [Show Timeline] 按钮,显示故事板(StoryBoard)编辑栏。在故事版中,我们建立两个关键帧,时间间隔大约在0.3秒。在前一个关键帧里,设置 ImageBack 控件的透明度(Opacity)为 50%,在第二个关键帧,设置 ImageBack 控件的透明度为 0%,并且将其大小(Scale)的 X 和 Y 值设置为 2。

12.jpg

提示:

整个按钮的效果就是:当用户点击按钮时,按钮图标略微变小、变淡,与此同时,按钮的背景处有另一个图标一边扩散、一边淡出。


接下来,选择 ImageFront 控件, 点击 [Source] 属性右侧的白色方块,设置 Template Binding 为 ImageSource。然后选择 ImageBack 控件,对其进行同样的操作。这一步操作,是将两个 ImageButton 控件的图片资源绑定到我们在一开始声明的 ImageSource 属性上,从而实现在实际使用 ImageButton 控件的地方,根据需求来指定不同的图标。由于模板内的 Image 控件不再是“硬编码”到某一特定的图片上,而是通过绑定来显示实际 ImageSource 属性所提供的值,因此我们就能够实现一个可以重复使用的按钮控件。

13.jpg

保存工作成果,然后点击界面上方的导航条,回到使用 ImageButton 控件的 page 编辑页面。

14.jpg

在该页面中,选择 ImageButton 控件,在属性栏中,找到 [ImageSource] 属性,为其指定任意一个图片资源。指定完成后,可以在预览区看到图片加载后的效果。

15.jpg

调整 ImageButton 控件的大小及位置,然后运行程序,在模拟器中查看效果。当点击该按钮时,会呈现如下效果。(部署到手机设备上体验,效果会更加明显) <IGNORE_JS_OP>1.jpg

OK。至此我们就完成定制 ImageButton 控件的全过程。

原文地址:https://www.cnblogs.com/zhibin/p/2553332.html