教你如何 构建基本的用户控件

创建一个简单用户控件是开始自定义控件的好方法。本章主要介绍创建一个基本的颜色拾取器。接下来分析如何将这个控件分解成功能更强大的基于模板的控件。

  创建基本的颜色拾取器很容易。然而,创建自定义颜色拾取器仍是有价值的联系,因为这不仅演示了构建控件的各种重要概念,而且提供了一个实用的功能。

  可为颜色拾取器创建自定义对话框。但如果希望创建能集成进不同窗口的颜色拾取器,使用自定义控件是更好的选择。最简单的自定义控件类型是用户控件,当设计窗口或页面时通过用户控件可以使用相同的方式组装多个元素。因为仅通过直接组合现有控件并添加功能并不能实现颜色拾取器,所以用户控件看起来是更合理的选择。

  典型的颜色拾取器允许用户通过单击颜色梯度中的某个位置或分别指定红、绿和蓝三元色成分来选择颜色。下图显示了创建的基本颜色拾取器。该颜色拾取器包含三个Slider控件,这些控件用于调节颜色成分,同时使用Rectangle元素预览选择的颜色。

一、定义依赖性属性

  创建颜色拾取器的第一步是为自定义控件库项目添加用户控件。当添加用户控件后,Visual Studio会创建XAML标记文件和相应的包含初始化代码即事件处理代码的自定义类。这与创建新的窗口或也卖弄是相同的——唯一的区别在与顶级容器是UserControl类:

复制代码

<UserControl x:Class="CustomControls.ColorPickerUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d"  Name="colorPicker">
</UserControl>

复制代码

  最简单的起点是设计用户控件对外界公开的公共接口。换句话说,就是设计控件使用者使用的鱼颜色拾取器进行交互的属性、方法和事件。

  最基本的细节是Color属性——毕竟,颜色拾取器不过是用于显示和选择颜色的特定工具。为支持WPF特性,如数据绑定、样式以及动画,控件的可写属性几乎都是依赖项属性。

  在前面章节中学习过,创建依赖项属性的第一步是为之定义静态字段,并在属性名称的后面加上单词Property:

public static DependencyProperty ColorProperty;

  Color属性将允许控件使用者通过代码设置或检索颜色值。然而,颜色拾取器中的滑动条控件也允许用户修改当前颜色的一个方面。为实现这一设计,当滑动条额值发生变化时,需要使用事件处理程序进行响应,并且响应地更新Color属性。但使用数据绑定关联滑动条会更加清晰。为使用数据绑定,需要将每个颜色成分定义为单独的依赖项属性:

public static DependencyProperty RedProperty;
public static DependencyProperty GreenProperty;
public static DependencyProperty BlueProperty;

  尽管Color属性存储了System.Windows.Media.Color对象,但Red、Green以及Blue属性将存储表示每个颜色成分的单个字节值。

  为属性定义静态字段只有第一步。还需要有静态构造函数,用于在用户控件中注册这些依赖性属性,指定属性的名称、数据类型以及拥有属性的控件类。可通过传递具有正确标记设置的FrameworkPropertyMetadata对象,在静态构造函数中指定选择的特定属性特性(如值继承)。还可指出在什么地方为验证、数据强制以及属性更改通知关联回调函数。

  在颜色拾取器中,只需要考虑一个因素——当各种属性变化时需要关联回调函数进行响应。因为Red、Green和Blue属性实际上时Color属性的不同表示,并且如果一个属性发生变化,就需要确保其他属性保持同步。

  下面是注册颜色拾取器的4个依赖性属性的静态构造函数的代码:

复制代码

static ColorPickerUserControl()
        {
            ColorProperty = DependencyProperty.Register("Color", typeof(Color),
                typeof(ColorPickerUserControl),
                new FrameworkPropertyMetadata(Colors.Black, new PropertyChangedCallback(OnColorChanged)));

            RedProperty = DependencyProperty.Register("Red", typeof(byte),
                typeof(ColorPickerUserControl),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged)));

            GreenProperty = DependencyProperty.Register("Green", typeof(byte),
                typeof(ColorPickerUserControl),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged)));

            BlueProperty = DependencyProperty.Register("Blue", typeof(byte),
                typeof(ColorPickerUserControl),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged)));
        }

复制代码

  现在已经定义了依赖性属性,可添加标准的属性封装器,使范文它们变得更加容易,并可在XAML中使用它们:

复制代码

public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, value); }
        }
public byte Red
        {
            get { return (byte)GetValue(RedProperty); }
            set { SetValue(RedProperty, value); }
        }

public byte Green
        {
            get{return (byte)GetValue(GreenProperty);}
            set{SetValue(GreenProperty,value);}
        }
public byte Blue
        {
            get { return (byte)GetValue(BlueProperty); }
            set { SetValue(BlueProperty, value); }
        }

 

  请记住,属性封装器不能包含任何逻辑,因为可直接使用DependencyObject基类的SetValue()和GetValue()方法设置和检索属性。例如,在这个示例中的属性同步逻辑是使用回调函数实现的,当属性发生变化时通过属性封装器或者直接调用SetValue()方法引发回调函数。

 

更多干货 请点击这里

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章