更新:2007 年 11 月
Windows Presentation Foundation (WPF) Designer for Visual Studio 的擴充性模型可讓您在設計階段為 [屬性] 視窗中的屬性建立自訂值編輯器。編輯器可以是內嵌編輯器,以便直接在 [屬性] 視窗中編輯值,也可以是擴充編輯器,能讓您提供額外的 UI,在 [屬性] 視窗以外編輯屬性。為了示範如何建立擴充編輯器,本逐步解說提供如何為控制項的 Background 屬性建立色彩編輯器的逐步程序。此擴充編輯器是從 [屬性] 視窗中的內嵌編輯器開啟。
在這個逐步解說中,您會執行下列工作:
建立 WPF 自訂控制項專案。
建立要當做擴充編輯器的使用者控制項。
建立內嵌編輯器,這可用來在 [屬性] 視窗中編輯屬性值,以及開啟擴充編輯器。
建立繼承自 ExtendedPropertyValueEditor 的類別,用來將編輯器連接至要為其提供自訂編輯的類別。
建立繼承自 IRegisterMetadata 的類別,以註冊新的擴充編輯器。
在設計階段測試擴充編輯器。
必要條件
您需要下列元件才能完成此逐步解說:
- Visual Studio 2008.
建立自訂控制項
第一個步驟是為自訂控制項建立專案。這個控制項是一個具有少量設計階段程式碼的簡易按鈕,這個程式碼使用 GetIsInDesignMode 方法來實作設計階段行為。
建立自訂控制項
在 Visual C# 中建立名為 CustomControlLibrary 的新 WPF 自訂控制項程式庫。
CustomControl1 的程式碼隨即在 [程式碼編輯器] 中開啟。
加入下列 WPF 設計工具組件的參考。
- Microsoft.Windows.Design
在 CustomControl1 的 [程式碼編輯器] 中,將 CustomControlLibrary 命名空間中的程式碼替換成下列程式碼:
public class CustomControl1 : Button { public CustomControl1() { if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) { Background = Brushes.Red; } } }將專案的輸出路徑設定為 "bin\"。
建置方案。
建立擴充編輯器的使用者控制項
先前程序中所建立的控制項是附加自訂色彩編輯器的目標。在這個程序中,您會建立另一個使用者控制項來當做擴充編輯器。
若要建立當做擴充編輯器的使用者控制項
將 Visual C# 中名為 CustomControlLibrary.Design 的新 WPF 自訂控制項程式庫專案加入到方案中。
CustomControl1 的程式碼隨即在 [程式碼編輯器] 中開啟。
在 [方案總管] 中,從 CustomControlLibrary.Design 專案刪除 CustomControl1 檔案。
加入下列 WPF 設計工具組件的參考。
- Microsoft.Windows.Design
加入 CustomControlLibrary 專案的參考。
將專案的輸出路徑設定為 "..\CustomControlLibrary\bin\"。這麼做會將控制項的組件和中繼資料組件保留在同一個資料夾中,讓設計工具可進行中繼資料探索。
將名為 ColorsList 的新類別加入到 CustomControlLibrary.Design 專案。
在 ColorsList 的 [程式碼編輯器] 中,以下列程式碼取代自動產生的程式碼。
using System; using System.Linq; using System.Collections.Generic; using System.Text; using System.Windows.Media; using System.Reflection; using System.Collections.ObjectModel; namespace ColorsListNamespace { public class ColorsList : ObservableCollection<Color> { public ColorsList() { Type type = typeof(Colors); foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.Static)) { if (propertyInfo.PropertyType == typeof(Color)) { Add((Color)propertyInfo.GetValue(null, null)); } } } } }將名為 ColorsListControl 的新使用者控制項 (WPF) 加入到 CustomControlLibrary.Design 專案。
ColorsListControl.xaml 的程式碼隨即在設計工具中開啟。
在 ColorsListControl.xaml 的 [XAML] 檢視中,將自動產生的 XAML 替換成下列 XAML。
<UserControl x:Class="ColorsListNamespace.ColorsListControl" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:Local="clr-namespace:ColorsListNamespace" xmlns:PropertyEditing="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design" Height="184" Width="260" Background="White"> <UserControl.Resources> <Local:ColorsList x:Key="colors"/> <Style TargetType="{x:Type Button}"> <EventSetter Event="Click" Handler="ItemsControl_Click"/> </Style> </UserControl.Resources> <ItemsControl ItemsSource="{Binding Source={StaticResource colors}}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <Border CornerRadius="5" > <WrapPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"> <ScrollViewer> <ItemsPresenter/> </ScrollViewer> </WrapPanel> </Border> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <Button Tag="{Binding}" Command="{x:Static PropertyEditing:PropertyValueEditorCommands.ShowInlineEditor}"> <Button.Template> <ControlTemplate> <Border Width="30" Height="30" BorderBrush="Black" BorderThickness="1" CornerRadius="5"> <Rectangle Width="22" Height="22" ToolTip="{Binding}"> <Rectangle.Fill> <SolidColorBrush Color="{Binding}"/> </Rectangle.Fill> </Rectangle> </Border> </ControlTemplate> </Button.Template> </Button> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </UserControl>在 [方案總管] 中,展開 ColorsListControl.xaml 並開啟 ColorsListControl.xaml.cs。
在 ColorsListControl 的 [程式碼編輯器] 中,以下列程式碼取代自動產生的程式碼。
using System; using System.Linq; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace ColorsListNamespace { public partial class ColorsListControl : System.Windows.Controls.UserControl { public static readonly RoutedEvent ClosePopupEvent = EventManager.RegisterRoutedEvent("ClosePopupEvent", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ColorsListControl)); public ColorsListControl() { InitializeComponent(); } public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorsListControl), new FrameworkPropertyMetadata(null)); public Color SelectedColor { get { return (Color)base.GetValue(SelectedColorProperty); } set { base.SetValue(SelectedColorProperty, value); } } public static readonly DependencyProperty SelectedBrushProperty = DependencyProperty.Register("SelectedBrush", typeof(SolidColorBrush), typeof(ColorsListControl), new FrameworkPropertyMetadata(null)); public SolidColorBrush SelectedBrush { get { return (SolidColorBrush)base.GetValue(SelectedBrushProperty); } set { base.SetValue(SelectedBrushProperty, value); } } public event RoutedEventHandler ClosePopup { add { AddHandler(ClosePopupEvent, value); } remove { RemoveHandler(ClosePopupEvent, value); } } protected void RaiseClosePopupEvent() { RoutedEventArgs newEventArgs = new RoutedEventArgs(ColorsListControl.ClosePopupEvent); RaiseEvent(newEventArgs); } private void ItemsControl_Click(object sender, RoutedEventArgs e) { SelectedColor = (Color)((Button)sender).Tag; SelectedBrush = new SolidColorBrush(SelectedColor); RaiseClosePopupEvent(); } } }建置方案。
將 ColorsListControl.xaml 重新載入設計工具,擴充編輯器 UI 應會出現在 [設計] 檢視中。
建立色彩編輯器的範本
色彩編輯器的內嵌編輯器不如擴充編輯器複雜,可使用 XAML 資料範本建立。您也會建立擴充編輯器的資料範本,它會指定使用前面程序中建立的使用者控制項。
若要建立色彩編輯器的範本
將名為 EditorResources 的新類別加入到 CustomControlLibrary.Design 專案。
在 EditorResources 的 [程式碼編輯器] 中,以下列程式碼取代自動產生的程式碼。
namespace ExtendedEditorNamespace { 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 的程式碼隨即在設計工具中開啟。
在 EditorResources.xaml 的 [XAML] 檢視中,將自動產生的 XAML 替換成下列 XAML。
<ResourceDictionary xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:PropertyEditing="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design" xmlns:Local="clr-namespace:ColorsListNamespace" xmlns:Media="clr-namespace:System.Windows.Media;assembly=PresentationCore" xmlns:sys="clr-namespace:System;assembly=mscorlib" x:Class="ExtendedEditorNamespace.EditorResources"> <DataTemplate x:Key="BrushExtendedEditorTemplate"> <Local:ColorsListControl SelectedBrush="{Binding Value, Mode=TwoWay}"/> </DataTemplate> <DataTemplate x:Key="BrushInlineEditorTemplate"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBox Grid.Column="0" Text="{Binding StringValue}"/> <PropertyEditing:EditModeSwitchButton Grid.Column="1"/> </Grid> </DataTemplate> </ResourceDictionary>建置方案。
封裝範本和註冊編輯器
困難的部分已經完成。現在您已為色彩編輯器建立了擴充和內嵌編輯器範本,接下來就可以建立類別來封裝它們,並向自訂控制項註冊它們。
若要封裝和註冊編輯器
將名為 BrushExtendedEditor 的新類別加入到 CustomControlLibrary.Design 專案。
在 BrushExtendedEditor 的 [程式碼編輯器] 中,以下列程式碼取代自動產生的程式碼。
namespace ExtendedEditorNamespace { using System; using System.Collections.Generic; using System.Text; using Microsoft.Windows.Design.PropertyEditing; using System.Windows; using ExtendedEditorNamespace; public class BrushExtendedEditor : ExtendedPropertyValueEditor { private EditorResources res = new EditorResources(); public BrushExtendedEditor() { this.ExtendedEditorTemplate = res["BrushExtendedEditorTemplate"] as DataTemplate; this.InlineEditorTemplate = res["BrushInlineEditorTemplate"] as DataTemplate; } } }將名為 Metadata 的新類別加入到 CustomControlLibrary.Design 專案。
在 Metadata 的 [程式碼編輯器] 中,以下列程式碼取代自動產生的程式碼。
namespace ExtendedEditorNamespace { 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(BrushExtendedEditor))); MetadataStore.AddAttributeTable(builder.CreateTable()); } } }建置方案。
測試色彩編輯器
您剛剛已完成建立色彩編輯器,現在只剩測試。若要測試編輯器,您要將 WPF 應用程式專案加入到方案,然後加入自訂控制項。您接著要變更 [屬性] 視窗中的 Background,檢視新編輯器的實際運作。
若要測試色彩編輯器
將 Visual C# 中名為 DemoApplication 的新 WPF 應用程式專案加入至方案。
Window1.xaml 隨即在 WPF 設計工具中開啟。
加入 CustomControlLibrary 專案的參考。
在 Window1.xaml 的 [XAML] 檢視中,將自動產生的 XAML 替換成下列 XAML。這個 XAML 會加入 CustomControlLibrary 命名空間的參考,並加入 CustomControl1 自訂控制項。按鈕會顯示在 [設計] 檢視中,背景為紅色,表示控制項處於設計模式。如果按鈕不顯示,您可能需要按一下設計工具頂端的資訊列以重新載入檢視。
<Window x:Class="DemoApplication.Window1" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://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] 屬性旁的下拉按鈕。這時會顯示視覺色彩編輯器,而非預設色彩清單。
從編輯器選取色彩。自訂控制項的背景就會變更為該色彩。