深入浅出:FlipPanel自定义控件开发全解析
立即解锁
发布时间: 2025-08-26 01:21:54 阅读量: 3 订阅数: 11 


Silverlight开发实战精要
### 深入浅出:FlipPanel 自定义控件开发全解析
#### 1. 开启 FlipPanel 类的开发
FlipPanel 本质上十分简单,它由两个内容区域构成,用户可在其中填充单个元素(通常是包含多种元素的布局容器)。严格来讲,FlipPanel 并非真正的面板,因为它不借助布局逻辑来组织子元素。不过,其结构清晰直观,不会引发问题。此外,FlipPanel 还设有一个翻转按钮,方便用户在两个内容区域间切换。
在创建自定义控件时,虽可从 ContentControl 或 Panel 等控件类派生,但 FlipPanel 直接继承自基础的 Control 类。若无需特定控件类的功能,这是最佳起点。除非想创建无标准控件和模板架构的元素,否则不应从更简单的 FrameworkElement 类派生。以下是 FlipPanel 类的基本定义:
```vb
Public Class FlipPanel
Inherits Control
...
End Class
```
接下来,要为 FlipPanel 创建属性。和大多数 Silverlight 元素的属性一样,应使用依赖属性。定义依赖属性分两步:首先要有一个共享定义,记录属性的元数据,如名称、类型、所属类类型及属性变更时触发的可选回调。以下是定义 FrontContent 属性的示例:
```vb
Public Shared ReadOnly FrontContentProperty As DependencyProperty = _
DependencyProperty.Register("FrontContent", GetType(Object), _
GetType(FlipPanel), Nothing)
```
然后,需添加传统的 .NET 属性过程,调用基类的 GetValue() 和 SetValue() 方法来更改依赖属性:
```vb
Public Property FrontContent() As Object
Get
Return MyBase.GetValue(FrontContentProperty)
End Get
Set(ByVal value As Object)
MyBase.SetValue(FrontContentProperty, value)
End Set
End Property
```
BackContent 属性的定义与之类似:
```vb
Public Shared ReadOnly BackContentProperty As DependencyProperty = _
DependencyProperty.Register("BackContent", GetType(Object), _
GetType(FlipPanel), Nothing)
Public Property BackContent() As Object
Get
Return MyBase.GetValue(BackContentProperty)
End Get
Set(ByVal value As Object)
MyBase.SetValue(BackContentProperty, value)
End Set
End Property
```
还需添加一个关键属性 IsFlipped,这是一个布尔属性,用于跟踪 FlipPanel 的当前状态(正向或反向),并允许控件使用者以编程方式翻转:
```vb
Public Shared ReadOnly IsFlippedProperty As DependencyProperty = _
DependencyProperty.Register("IsFlipped", GetType(Boolean), _
GetType(FlipPanel), Nothing)
Public Property IsFlipped() As Boolean
Get
Return CBool(MyBase.GetValue(IsFlippedProperty))
End Get
Set(ByVal value As Boolean)
MyBase.SetValue(IsFlippedProperty, value)
ChangeVisualState(True)
End Set
End Property
```
注意,IsFlipped 属性的设置器调用了 ChangeVisualState() 方法,该方法确保显示内容与当前翻转状态匹配。
FlipPanel 从 Control 类继承了大部分所需属性,不过 CornerRadius 属性除外。Control 类有 BorderBrush 和 BorderThickness 属性可绘制边框,但缺少像 Border 元素那样将方形边缘圆角处理的 CornerRadius 属性。在 FlipPanel 中实现此效果很简单,只需添加 CornerRadius 属性,并在默认控件模板中用它配置 Border 元素:
```vb
Public Shared ReadOnly CornerRadiusProperty As DependencyProperty = _
DependencyProperty.Register("CornerRadius", GetType(CornerRadius), _
GetType(FlipPanel), Nothing)
Public Property CornerRadius() As CornerRadius
Get
Return CType(GetValue(CornerRadiusProperty), CornerRadius)
End Get
Set(ByVal value As CornerRadius)
SetValue(CornerRadiusProperty, value)
End Set
End Property
```
#### 2. 使用 Generic.xaml 添加默认样式
自定义控件存在先有鸡还是先有蛋的难题:编写控件类代码时需考虑控件模板类型,但创建控件模板又需了解控件的工作方式。
解决方案是同时构建控件类和默认控件模板。可将控件类放在 Silverlight 类库的任意代码文件模板中,而控件模板必须放在名为 generic.xaml 的文件里。若类库包含多个控件,其默认模板都要放在同一个 generic.xaml 文件中。添加该文件的步骤如下:
1. 在解决方案资源管理器中右键单击类库项目,选择“添加” -> “新建文件夹”。
2. 将新文件夹命名为 Themes。
3. 右键单击 Themes 文件夹,选择“添加” -> “新建项”。
4. 在“添加新项”对话框中,选择 XML 文件模板,输入名称 generic.xaml,然后点击“添加”。
generic.xaml 文件包含一个资源字典,其中有自定义控件的样式。每个自定义控件都要添加一个样式,且样式必须设置相应控件的 Template 属性以应用默认控件模板。
在 generic.xaml 文件中,需声明资源字典,并将项目命名空间映射到 XML 命名空间前缀,以便在标记中访问自定义控件。示例如下:
```xml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FlipPanelControl;assembly=FlipPanelControl">
...
</ResourceDictionary>
```
注意,映射控件命名空间时,要同时包含项目命名空间和项目程序集名称,这与在 Silverlight 应用程序中使用自定义类不同。因为自定义控件会在其他应用程序中使用,若不指定程序集,Silverlight 会默认使用应用程序程序集。
在资源字典内,可为控件定义样式,示例如下:
```xml
<Style TargetType="local:FlipPanel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:FlipPanel">
...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
```
最后,要让控件从 generic.xaml 文件中获取默认样式,需在构造函数中设置控件的 DefaultStyleKey 属性:
```vb
Public Sub New()
DefaultStyleKey = GetType(FlipPanel)
End Sub
```
DefaultStyleKey 指示用于查找样式的类型。在此例中,样式的 TargetType 为 FlipPanel,所以 DefaultStyleKey 也需使用该类型。多数情况下都遵循此模式,除非从现有控件类派生更专业的控件,此时可选择保留原构造函数逻辑并继承基类的标准样式。
#### 3. 选择部件和状态
现在有了基本结构,可确定控件模板中要使用的部件和状态。
FlipPanel 需要两种状态:
- **Normal**:此故事板确保只有前面的内容可见,后面的内容被翻转、淡化或以其他方式移出视线。
- **Flipped**:此故事板确保只有后面的内容可见,前面的内容被动画移出。
此外,还需要两个部件:
- **FlipButton**:点击此按钮可在前后视图间切换,FlipPanel 通过处理该按钮的事件提供此功能。
- **FlipButtonAlternate**:这是一个可选元素,功能与 FlipButton 相同。包含它可让控件使用者在自定义控件模板中采用两种不同方式,一种是在可翻转内容区域外使用单个翻转按钮,另一种是在面板两侧的可翻转区域分别放置一个翻转按钮。
为表明 FlipPanel 使用这些部件和状态,需将 TemplatePart 属性应用于控件类,示例如下:
```vb
<TemplateVisualState(Name := "Normal", GroupName := "ViewStates"), _
TemplateVisualState(Name := "Flipped", GroupName := "ViewStates"), _
TemplatePart(Name := "FlipButton", Type := GetType(ToggleButton)), _
TemplatePart(Name := "FlipButtonAlternate", Type := GetType(ToggleButton))> _
Public Class FlipPanel
Inherits Control
...
End Class
```
FlipButton 和 FlipButtonAlternate 部件有限制,每个都只能是 ToggleButton 或其派生类的实例。
部件和状态的命名约定较为简单:命名部件或状态时,不要包含前缀或后缀,如使用 Flipped 和 FlipButton 而非 FlippedState 和 FlipButtonPart。例外是状态组,应始终以 States 结尾,如 ViewStates。同时,参考 Silverlight 框架中类似控件并使用相同名称会有帮助,尤其是需要使用 Co
0
0
复制全文
相关推荐









