WPF控件开发之自定义控件(2)

属性的元数据。元数据包含该属性的默认值、CoerceValueCallback 和 PropertyChangedCallback。

通过实现该属性的 get 和 set 访问器,定义一个名为 Value 的 CLR“包装”属性,这个名称也就是用来注册该依赖项属性的名称。请注意,get 和 set 访问器只是分别调用 GetValue 和 SetValue。建议依赖项属性的访问器不要包含其他逻辑,这是因为客户端和 WPF 可绕过这两个访问器直接调用 GetValue 和 SetValue。例如,如果属性绑定到数据源,则不会调用该属性的 set 访问器。不要向 get 和 set 访问器添加其他逻辑,而应使用 ValidateValueCallback、CoerceValueCallback 和 PropertyChangedCallback 委托在值更改时进行响应或检查该值。

为 CoerceValueCallback 定义一个名为 CoerceValue 的方法。CoerceValue 确保 Value 大于或等于 MinValue 且小于或等于 MaxValue。

为 PropertyChangedCallback 定义一个名为 OnValueChanged 的方法。OnValueChanged 创建一个 RoutedPropertyChangedEventArgs<(Of <(T>)>) 对象,并准备引发 ValueChanged 路由事件。路由事件在下一节中讨论。

使用 RoutedEvent
就像依赖项属性以附加功能扩展 CLR 属性的用途一样,路由事件扩展了标准 CLR 事件的用途。在创建新的 WPF 控件时,将事件实现为路由事件也是一种好方法,这是因为路由事件支持以下行为:

事件可以在多个控件的父级上进行处理。如果事件是冒泡事件,则元素树中的单个父级可预订该事件。然后,应用程序作者可以使用一个处理程序来响应多个控件的该事件。例如,如果控件属于 ListBox 中的每个项(因为它包含在 DataTemplate 中),则应用程序开发人员可以为该控件的 ListBox 事件定义相应的事件处理程序。每当这些控件中的任何控件发生该事件时,都会调用该事件处理程序。

路由事件可在 EventSetter 中使用,应用程序开发人员通过 EventSetter 可以在样式内指定事件的处理程序。

路由事件可在 EventTrigger 中使用,这对于使用 XAML 对属性进行动画处理很有用。

下面的示例定义了一个路由事件。

WPF控件开发之自定义控件(2)_第1张图片 

这段代码执行下面的操作:

将一个名为 ValueChangedEvent 的 RoutedEvent 标识符定义为 publicstaticreadonly 字段。

通过调用 EventManager..::.RegisterRoutedEvent 方法注册路由事件。该示例在调用 RegisterRoutedEvent 时指定以下信息:

事件的名称为 ValueChanged。

路由策略为 Bubble,这意味着首先调用源(引发事件的对象)上的事件处理程序,然后从最近的父元素上的事件处理程序开始,相继调用源的各个父元素上的事件处理程序。

该事件处理程序的类型为 RoutedPropertyChangedEventHandler<(Of <(T>)>),是用 Decimal 类型构造的。

该事件的所属类型为 NumericUpDown。

声明一个名为 ValueChanged 的公共事件,并包含事件访问器声明。该示例调用 add 访问器声明中的 AddHandler 和 remove 访问器声明中的 RemoveHandler 来使用 WPF 事件服务。

创建一个名为 OnValueChanged 的受保护的虚方法,该方法引发 ValueChanged 事件。

使用绑定
若要将控件 UI 与其逻辑分离,请考虑使用数据绑定。如果是使用 ControlTemplate 定义控件的外观,这一点尤其重要。使用数据绑定时,可能能够避免引用 UI 的特定部分。

下面的示例更新 NumericUpDown 控件的 TextBlock,向它分配一个名称,然后在代码中按名称引用该文本框。

 

 

下面的示例使用绑定来达到相同的目的。

WPF控件开发之自定义控件(2)_第2张图片   

针对设计器设计
若要在 Visual Studio Windows Presentation Foundation (WPF) 设计器中获得对自定义 WPF 控件的支持(例如,使用“属性”窗口编辑属性),请遵循以下准则。

依赖项属性
确保实现 CLRget 访问器和 set 访问器,如前面“使用依赖项属性”中所述。设计器可以使用包装来检测某个依赖项属性是否存在,但与 WPF 和控件客户端一样,在获取或设置属性时不需要使用设计器来调用访问器。

附加属性
应按照以下原则在自定义控件上实现附加属性:

具有一个使用 RegisterAttached 方法创建的 publicstaticreadonlyDependencyProperty,其形式为“属性名称Property”。传递到 RegisterAttached 的属性名称必须与属性名称 匹配。

实现一对名为 Set属性名称 和 Get属性名称 的 public static CLR 方法。这两种方法都应接受从 DependencyProperty 派生的类作为其第一个参数。Set属性名称 方法还接受其类型与属性的注册数据类型匹配的参数。Get属性名称 方法应返回相同类型的值。如果缺少 Set属性名称 方法,则该属性标记为只读。

Set 属性名称 和 Get属性名称 必须分别直接路由到目标依赖项对象的 GetValue 和 SetValue 方法。通过调用方法包装或直接调用目标依赖项对象,设计器可以访问附加属性。

你可能感兴趣的:(WPF学习笔记,wpf,datatemplate,程序开发,扩展,windows,ui)