简单易学图文并茂创作控件自己创作控件,分三种主要的形式:复合控件,扩展控件,和自定义控件。
复合控件,顾名思义就是把现有的进行组合,让它们协作形成功能强大的新控件;扩展控件,是以某一现有控件为基础,让它具有新的功能;自定义控件,则是由作者完全操刀,建立一个全新的控件。
可以用一个比喻来理解这三种形式的区别:复合控件,就是你买好各个电脑配件,组装成一台电脑;扩展控件,就是把显卡上的零件更换几个,让它能力比标准产品更强大;自定义控件,就是自己制作一个名为“生人勿近”的硬件,他可以通过PCI插槽,安装到电脑上,一旦生人走近,它能识别并发出狗叫……综上,三种形式中,复合控件相对来说是最简单的;扩展控件在其次;自定义控件最难。
通常,我们使用前两种技术,就能创作出很复杂的控件了。
范例1:Excel的单元格Cell,当它没有焦点的时候,就是一个TextBlock,当它获得焦点,可以编辑的时候,就是一个TextBox框。
这样一个控件,将是我们今后制作表格控件的基础。
范例1中,我们会用到两种技术,复合控件和扩展控件。
在VS中,要进行如下的工作(推荐使用VS2010)1.新建一个Solution,名为Cell;2.添加一个名为“TestAPP”的WFP项目。
我们用他来测试成果;3.添加一个名为“Ctrl_Cell”的WFP用户控件项目。
然后,我们需要一个TextBlock,和一个TextBox控件,这是我们的演员。
考虑一下它们应该怎样演出,才能达到我们需要的效果:●平时这个控件,应该表现出TextBlock的外观;●当我们点击这个Label时,隐藏的TextBox控件跑到TextBlock的前面,并且它显示的值和TextBlock一样。
同时,这个值是可以编辑的;●编辑完TextBox的内容,按下Enter,或者点击屏幕上的其他控件,让TextBox失去焦点,TextBox消失。
TextBlock跑到前面来,并且显示编辑后的内容。
接着,需要考虑一下这个控件的属性和事件。
1.它应该有一个Value属性,Label显示这个Value;同时Text也显示这个Value;我们编辑的时候,也是针对这个Value。
2.点击TextBlock时,会发生一系列的变化。
所以我们要关注TextBlock的MouseDown事件。
3.编辑TextBox,按下Enter后,或者TextBox失去焦点,会发生一系列的变化。
所以我们要关注TextBox接受了Enter键这个输入,同时也要关注它的LostFocus事件。
关于“TextBox控件接受到一个Enter输入”的问题。
基础的TextBox控件是没有这个功能的,而我们今后要用到的地方很多。
所以我考虑扩展一下TextBox的功能,制作一个Ex_TextBox。
新的控件在用户按下Enter的时候,产生一个getEnterKey的事件,这样使用者就能处理这条消息了。
扩展现有控件,直接在原有的TextBox上继承,把一个判断键盘输入值的程序afterGetEnter绑定到Keydown事件下。
在Ctrol_Cell项目下,添加一个新的类,名为Ex_TextBox。
*******************代码********************Public Class Ex_TextBoxInherits TextBox'这个控件扩展了现有TextBox的功能。
'当用户输入Enter的时候,引发一个getEnterKey事件。
'这样,控件的使用者,就能在输入Enter的时候,得到一个信息。
'扩展控件功能,属于创作控件的第二种技术。
Public Event getEnterKey As EventHandlerPrivate Sub afterGetEnter(ByVal sender As Object, ByVal e As KeyEventArgs) Handles MyBase.KeyDownIf e.Key = Key.Enter ThenRaiseEvent getEnterKey(sender, e)End IfEnd SubEnd Class*******************代码********************如此,用户按下Enter后,Ex_TextBox就发出一个getEnterKey事件。
使用者今后编写响应这个事件的代码就可以了。
最后,我们在Cell的UI上,添加一个TextBlock和一个Ex_TextBox。
其UI代码如下:*******************代码********************<UserControl x:Class="Ctrl_Cell"xmlns="/winfx/2006/xaml/presentation"xmlns:x="/winfx/2006/xaml"xmlns:mc="/markup-compatibility/2006"xmlns:d="/expression/blend/2008"mc:Ignorable="d"d:DesignHeight="300" d:DesignWidth="182" Height="23" xmlns:my="clr-namespace:Ctrl_Label_Text"><Grid><TextBlock Height="23" HorizontalAlignment="Stretch" Margin="0" Name="TextBlock1" Text="TextBlock" VerticalAlignment="Top" Background="#FF8DD66D" Padding="1" /><my:Ex_TextBox Height="23" HorizontalAlignment="Stretch" Margin="0" x:Name="Ex_TextBox1" VerticalAlignment="Stretch" Width="Auto" Visibility="Hidden" VerticalScrollBarVisibility="Hidden" Background="#FF8DD66D" BorderThickness="0" /> </Grid></UserControl>*******************代码********************控件的外观如下:要添加Value属性,并描述控件的行为,还需要添加一些代码:*******************代码********************Public Class Ctrl_CellPrivate p_value As String '这是Cell的Value属性Public Property Value As StringGetReturn Me.p_valueEnd GetSet(ByVal value As String)Me.p_value = valueMe.TextBlock1.Text = valueEnd SetEnd PropertyPrivate Sub ShowExTextBox(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBlock1.MouseDown'把显示Ex_TextBox的动作,和点击TextBlock事件绑定起来Me.Ex_TextBox1.Visibility = Windows.Visibility.VisibleMe.TextBlock1.Visibility = Windows.Visibility.HiddenMe.Ex_TextBox1.Focus()End SubPrivate Sub MyInit()'把显示TextBlock的动作,和Ex_Textbox得到Enter,以及失去焦点这两个事件绑定起来AddHandler Ex_TextBox1.getEnterKey, AddressOf Me.ShowTextBlockAddHandler Ex_TextBox1.LostFocus, AddressOf Me.ShowTextBlockEnd SubPrivate Sub ShowTextBlock(ByVal sender As Object, ByVal e As System.EventArgs) '这是从Ex_TextBox切换到TextBlock的动作Me.TextBlock1.Visibility = Windows.Visibility.VisibleMe.Value = Me.Ex_TextBox1.TextMe.Ex_TextBox1.Visibility = Windows.Visibility.HiddenEnd SubPublic Sub New()' 此调用是设计器所必需的。
InitializeComponent()' 在InitializeComponent() 调用之后添加任何初始化。
Me.MyInit() '调用自己的初始化代码End SubEnd Class*******************代码********************这样,Cell的设计就完成了。
在TestAPP中测试一下:在UI上放一个Cell控件。
并添加一个按钮:按钮查看Cell的Value,代码如下:*******************代码********************Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.ClickMsgBox(Me.Cell1.Value)End Sub*******************代码********************当Cell没有点击的时候,它是一个TextBlock;点击它,变成一个TextBox,可以接受用户的输入;修改内容并按下Enter后,切换回TextBlock,内容也修改了;修改内容,直接点击旁边的按钮,也能切换回TextBlock;按钮显示的是Cell的值。