更新:2007 年 11 月
使用 Visual Studio Windows Presentation Foundation (WPF) 设计器的扩展性模型,可以在设计时,在“属性”窗口中为属性创建自定义值编辑器。编辑器可以是内联编辑器(允许您在“属性”窗口中直接编辑值),也可以是扩展编辑器(允许您提供用来在“属性”窗口外部编辑属性的其他 UI)。为了演示如何创建内联编辑器,本演练提供了为控件的 Background 属性创建内联值编辑器的分步过程。
在本演练中,您将执行下列任务:
您需要以下组件来完成本演练:
第一步是为自定义控件创建项目。该控件是一个带有少量设计时代码的简单按钮,该按钮使用 GetIsInDesignMode 方法来实现设计时行为。
创建自定义控件
使用 Visual C# 创建一个名为 CustomControlLibrary 的新 WPF 自定义控件库项目。
CustomControl1 的代码在“代码编辑器”中打开。
添加对以下 WPF 设计器程序集的引用。
在 CustomControl1 的代码编辑器中,用下面的代码替换 CustomControlLibrary 命名空间中的代码:
public class CustomControl1 : Button
{
public CustomControl1()
{
if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
Background = Brushes.Red;
}
}
}
将项目的输出路径设置为“bin\”。
生成解决方案。
内联编辑器可以用 XAML 数据模板创建。这将是一个简单的下拉列表,其中显示 Background 属性的颜色选项列表。
为内联编辑器创建模板
使用 Visual C# 向解决方案中添加一个名为 CustomControlLibrary.Design 的新 WPF 自定义控件库项目。
CustomControl1 的代码在“代码编辑器”中打开。
在“解决方案资源管理器”中,将 CustomControl1 文件从 CustomControlLibrary.Design 项目中删除。
添加对以下 WPF 设计器程序集的引用。
添加对 CustomControlLibrary 项目的引用。
将项目的输出路径设置为“..\CustomControlLibrary\bin\”。这样可使控件的程序集与元数据程序集位于同一文件夹中,从而可为设计器启用元数据发现。
向 CustomControlLibrary.Design 项目中添加一个名为 EditorResources 的新类。
在 EditorResources 的代码编辑器中,用下面的代码替换自动生成的代码。
namespace InlineEditorNamespace
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
public partial class EditorResources : ResourceDictionary {
public EditorResources()
: base()
{
InitializeComponent();
}
}
}
在“项目”菜单中,单击“添加资源字典”。
将该文件命名为 EditorResources.xaml 并单击“添加”。
在 EditorResources 的 XAML 视图中,用下面的 XAML 替换自动生成的 XAML。
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PropertyEditing="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design"
xmlns:Media="clr-namespace:System.Windows.Media;assembly=PresentationCore"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="InlineEditorNamespace.EditorResources">
<DataTemplate x:Key="BrushInlineEditorTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" Text="{Binding StringValue}">
<ComboBoxItem>Red</ComboBoxItem>
<ComboBoxItem>Blue</ComboBoxItem>
<ComboBoxItem>Green</ComboBoxItem>
</ComboBox>
</Grid>
</DataTemplate>
</ResourceDictionary>
生成解决方案。
在为内联编辑器创建了模板之后,现在必须创建一个继承自 PropertyValueEditor 的类以便将该模板用作自定义编辑器,而且必须注册新的内联编辑器。
封装并注册内联编辑器
向 CustomControlLibrary.Design 项目中添加一个名为 BrushInlineEditor 的新类。
在 BrushInlineEditor 的代码编辑器中,用下面的代码替换自动生成的代码。
namespace InlineEditorNamespace
{
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Windows.Design.PropertyEditing;
using System.Windows;
using InlineEditorNamespace;
public class BrushInlineEditor : PropertyValueEditor
{
private EditorResources res = new EditorResources();
public BrushInlineEditor()
{
this.InlineEditorTemplate = res["BrushInlineEditorTemplate"] as DataTemplate;
}
}
}
向 CustomControlLibrary.Design 项目中添加一个名为 Metadata 的新类。
在 Metadata 的代码编辑器中,用下面的代码替换自动生成的代码。
namespace InlineEditorNamespace
{
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Windows.Design.Metadata;
using System.ComponentModel;
using Microsoft.Windows.Design.PropertyEditing;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows;
using CustomControlLibrary;
// Container for any general design-time metadata that we want to initialize.
// Designers will look for a type in the design-time assembly that implements IRegisterMetadata.
// If found, they will instantiate it and call its Register() method automatically.
internal class Metadata : IRegisterMetadata
{
// Called by Cider to register any design-time metadata
public void Register()
{
AttributeTableBuilder builder = new AttributeTableBuilder();
builder.AddCustomAttributes
(typeof(CustomControl1),
Control.BackgroundProperty,
PropertyValueEditor.CreateEditorAttribute(
typeof(BrushInlineEditor)));
MetadataStore.AddAttributeTable(builder.CreateTable());
}
}
}
生成解决方案。
内联值编辑器现在已经完成,可以开始使用了。剩下的工作就是对其进行测试。若要测试内联编辑器,需要向您的项目中添加一个 WPF 应用程序,向该 WPF 应用程序中添加自定义控件,并查看操作中的内联编辑器。
测试内联值编辑器
使用 Visual C# 向解决方案中添加一个名为 DemoApplication 的新 WPF 应用程序项目。
Window1.xaml 在 WPF 设计器中打开。
添加对 CustomControlLibrary 项目的引用。
在 Window1.xaml 的 XAML 视图中,用下面的 XAML 替换自动生成的 XAML。此 XAML 将添加对 CustomControlLibrary 命名空间的引用并添加 CustomControl1 自定义控件。该按钮将出现在设计视图中而且将具有红色背景,这表明该控件处于设计模式下。如果该按钮未出现,则可能需要单击设计器顶部的信息栏以重新加载视图。
<Window x:Class="DemoApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" xmlns:my="clr-namespace:CustomControlLibrary;assembly=CustomControlLibrary">
<Grid>
<my:CustomControl1 Margin="30,30,30,30" Name="customControl11">Button</my:CustomControl1>
</Grid>
</Window>
在设计视图中选择该控件。
在“属性”窗口中,单击“Background”属性旁边的下拉按钮。将显示一个小型的、表示新内联编辑器的颜色选项列表(而不是默认的颜色列表)。颜色选项包括“红色”、“蓝色”和“绿色”。
从下拉列表中选择一种颜色。自定义控件的背景色将更改为所选颜色。
对于更复杂的属性编辑器,请参见演练:实现颜色编辑器,该主题演示如何创建扩展编辑器。
任务
其他资源