依赖属性与路由事件详解
立即解锁
发布时间: 2025-08-13 03:15:52 阅读量: 10 订阅数: 36 

### 依赖属性与路由事件详解
#### 1. 附加属性的定义与使用
在定义附加属性时,需使用 `DependencyProperty.RegisterAttached()` 方法,而非 `Register()` 方法。以 `Grid` 类中注册的 `Grid.Row` 附加属性为例:
```vbnet
RowProperty = DependencyProperty.RegisterAttached( _
"Row", GetType(Integer), GetType(Grid), Nothing)
```
`RegisterAttached()` 方法的参数与 `Register()` 方法完全相同。创建附加属性时,无需定义 .NET 属性包装器,因为附加属性可设置在任何依赖对象上。例如,`Grid.Row` 属性可设置在 `Grid` 对象(若有嵌套 `Grid`)或其他元素上,甚至元素不在 `Grid` 中,或元素树中没有 `Grid` 对象时也能设置。
附加属性需要一对共享方法来设置和获取属性值,这些方法使用从 `DependencyObject` 类继承的 `SetValue()` 和 `GetValue()` 方法。共享方法应命名为 `SetPropertyName()` 和 `GetPropertyName()`。以 `Grid.Row` 属性为例:
```vbnet
Public Shared Sub SetRow(ByVal element As UIElement, ByVal value As Integer)
element.SetValue(Grid.RowProperty, value)
End Sub
Public Shared Function GetRow(ByVal element As UIElement) As Integer
Return CInt(element.GetValue(Grid.RowProperty))
End Function
```
以下是使用代码将元素置于 `Grid` 第一行的示例:
```vbnet
Grid.SetRow(txtElement, 0)
```
此代码将 `txtElement`(一个 `TextBox`)的 `Grid.Row` 属性设置为 0。由于 `Grid.Row` 是附加属性,Silverlight 允许将其应用于任何其他元素。
#### 2. WrapBreakPanel 示例
`WrapBreakPanel` 通常表现得像 `WrapPanel`,但它添加了一个新功能:可通过附加属性在任意位置强制换行。
首先,定义 `WrapBreakPanel` 类:
```vbnet
Public Class WrapBreakPanel
Inherits System.Windows.Controls.Panel
...
End Class
```
为 `WrapBreakPanel` 定义 `Orientation` 属性,使用 `System.Windows.Controls.Orientation` 数据类型:
```vbnet
Public Shared ReadOnly OrientationProperty As DependencyProperty = _
DependencyProperty.Register("Orientation", GetType(Orientation), _
GetType(WrapBreakPanel), New PropertyMetadata(Orientation.Horizontal))
Public Property Orientation() As Orientation
Get
Return CType(GetValue(OrientationProperty), Orientation)
End Get
Set(ByVal value As Orientation)
SetValue(OrientationProperty, value)
End Set
End Property
```
在 Silverlight 页面中使用 `WrapBreakPanel` 时,可像设置其他属性一样设置 `Orientation` 属性:
```xml
<local:WrapBreakPanel Margin="5" Orientation="Vertical">
...
</local:WrapBreakPanel>
```
`WrapBreakPanel` 还包含一个附加属性 `LineBreakBefore`,允许任何子元素强制换行:
```vbnet
Public Shared LineBreakBeforeProperty As DependencyProperty = _
DependencyProperty.RegisterAttached("LineBreakBefore", GetType(Boolean), _
GetType(WrapBreakPanel), Nothing)
Public Shared Function GetLineBreakBefore(ByVal element As UIElement) As Boolean
Return CBool(element.GetValue(LineBreakBeforeProperty))
End Function
Public Shared Sub SetLineBreakBefore(ByVal element As UIElement, _
ByVal value As Boolean)
element.SetValue(LineBreakBeforeProperty, value)
End Sub
```
修改 `MeasureOverride()` 和 `ArrangeOverride()` 方法以检查强制换行:
```vbnet
' Check if the element fits in the line, or if a line break was requested.
If (currentLineSize.Width + desiredSize.Width > constraint.Width) _
OrElse WrapBreakPanel.GetLineBreakBefore(element) Then
...
End If
```
使用此功能时,只需将 `LineBreakBefore` 属性添加到元素中:
```xml
<local:WrapBreakPanel Margin="5" Background="LawnGreen">
<Button Width="50" Content="Button"></Button>
<Button Width="150" Content="Wide Button"></Button>
<Button Width="50" Content="Button"></Button>
<Button Width="150" Content="Button with a Break"
local:WrapBreakPanel.LineBreakBefore="True" FontWeight="Bold"></Button>
<Button Width="150" Content="Wide Button"></Button>
<Button Width="50" Content="Button"></Button>
</local:WrapBreakPanel>
```
#### 3. 路由事件概述
Silverlight 借鉴了 WPF 的部分路由事件模型,但形式大大简化。WPF 支持多种类型的路由事件,而 Silverlight 仅允许一种:冒泡事件,即从深层嵌套元素向其容器上升的事件。此外,Silverlight 的事件冒泡与一些键盘和鼠标输入事件(如 `MouseMove` 和 `KeyDown`)相关,且仅由少数低级元素支持。Silverlight 不会为高级控件事件(如 `Click`)使用事件冒泡,也不能在自定义控件的事件中使用事件路由。
#### 4. 核心元素事件
元素从两个核心类 `UIElement` 和 `FrameworkElement` 继承基本事件集。所有 Silverlight 元素都派生自这两个元素。
`UIElement` 类定
0
0
复制全文
相关推荐









