为了达到代码重用的目的,无论是ASP.net还是Silverlight或者其他什么,自定义控件都是必不可少的。当然自定义控件的作用并不仅仅是代码重用而已,这里就不多说了。在Silverlight中自定义控件共有两种,称其为UserControl和CustomControl。这两种控件是有很区别的,曾有人专门写过文章讨论什么时候该用哪种控件,我觉得简单来说,如果你并不期待控件能够被继承,那么就可以使用UserControl,否则用CustomControl。UserControl是有Xaml的,因此不能继承。你会发现微软提供的控件都能继承,它们都是CustomControl。那么是不是说CustomControl就比较高级,也不尽然,UserControl用起来比较方便,并且比较不容易出现CustomControl的一些问题(由于CustomControl的加载顺序很诡异,可能会导致一些意想不到的错误——如果你对这些顺序等不是特别清楚的话)。
说了那么多,那该如何创建自定义控件呢?首先来讲比较简单的UserControl,这里所谓的UserControl其实跟一般的页面没什么分别。举个例子吧,现在来做一个UserControl,功能很简单,就有一个按钮,然后设置一些标志表示它是UserControl。
新建一个工程,名为“TestUserControl”,在工程名上右键,选“添加”->“新项目”,弹出对话框,随便起个名字,就叫“MyUserControl”吧,如下图所示:
好了,UserControl创建好了,已经可以使用了,可以看到,除了名字外其他跟page是一样的。现在就添加一个按钮,并把背景设为红色吧,上面写几个字“我是User Control”。
<UserControl x:Class="TestUserControl.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="110" Height="40">
<Grid x:Name="LayoutRoot" Background="White">
<Button x:Name="button" Background="Red" Content="我是User Control"></Button>
</Grid>
</UserControl>
现在可以在Page页面中使用这个UserControl了,回到Page页面,为了使用此控件还需要添加命名空间,否则程序不知道去哪里找这个东西啊。
<UserControl x:Class="TestUserControl.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:uc="clr-namespace:TestUserControl"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<uc:MyUserControl></uc:MyUserControl>
</Grid>
</UserControl>
注意上面的XAML代码,首先添加了命名空间xmlns:uc="clr-namespace:TestUserControl",这个就是UserControl所处的命名空间,当然如果你写在其他的工程中就引用其他的命名空间。之后就可以通过“uc:”来使用该命名空间中的控件了。当然了,xmlns并不是UserControl特有的,Grid中也可以声明,比如可以这样用
<UserControl x:Class="TestUserControl.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White" xmlns:uc="clr-namespace:TestUserControl">
<uc:MyUserControl></uc:MyUserControl>
</Grid>
</UserControl>
但是并不推荐这样,因为这样出了Grid,uc就不能用了,而且貌似要多编译几次才能通过,汗。。。
上面两种方法的效果是一样的,都是添加了这样一个按钮:
光是这个样子是不是觉得太简单了,而且貌似没什么用?的确,但是你可以把UserControl写得很复杂,如果要重复使用的话就会很方便。话说按钮上的字都是写死的,那有什么意思?好,那就写一个属性,这个属性就能改变Button上面显示的字。这里可能要涉及一个比较复杂的东西,现在暂时不讲了,一时半会也讲不清楚,直接拿来用了,这就是DependencyProperty。定义属性的代码如下:
#region Text
public readonly static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MyUserControl), new PropertyMetadata(null, new PropertyChangedCallback(TextPropertyChangeCallBack)));
public string Text
{
get { return GetValue(TextProperty).ToString(); }
set { SetValue(TextProperty, value); }
}
public static void TextPropertyChangeCallBack(DependencyObject o,DependencyPropertyChangedEventArgs e)
{
MyUserControl userControl = o as MyUserControl;
if (userControl != null)
{
userControl.button.Content = e.NewValue.ToString();
}
}
#endregion
为了定义一个属性居然要写那么多代码,可能有人会说这真是麻烦透顶,跟一个public的字段有什么不同呢?当然是有不同的,这就要深入去了解DependencyProperty ,这里不提,只说我们做了一件事,在回调函数TextPropertyChangeCallBack中,如果Text的值改变了就更新按钮的Content,这就是我们的目的。好了,现在试试看吧,在Page页面中这样用:
<uc:MyUserControl Text="用了自定义属性"></uc:MyUserControl>
看,结果变成这样了:
好了,UserControl最基础的知识也就那么多了,其实还是有很多能深入的地方的,有机会再说了。