如何:创建对话框属性值编辑器

更新:2007 年 11 月

下面的代码示例演示如何为 Visual Studio Windows Presentation Foundation (WPF) 设计器实现自定义对话框属性值编辑器。 

示例

本主题演示如何创建一个对话框属性值编辑器,当在“属性”窗口中单击自定义的“文件名”属性时,该编辑器将显示一个“打开文件”对话框。

using System;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows;

namespace CustomControlLibrary
{
    public partial class DemoControl : UserControl
    {
        public DemoControl()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty FileNameProperty = DependencyProperty.Register(
            "FileName", 
            typeof(string), 
            typeof(DemoControl), 
            new PropertyMetadata("File name not set."));

        public string FileName
        {
            get
            {
                return (string)this.GetValue(FileNameProperty);
            }

            set
            {
                this.SetValue(FileNameProperty, value);
            }
        }
    }
}
<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:CustomControlLibrary.Design"
                    x:Class="CustomControlLibrary.Design.EditorResources">

    <DataTemplate x:Key="FileBrowserInlineEditorTemplate">
        <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>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CustomControlLibrary.Design
{
    using System.Windows;
    public partial class EditorResources : ResourceDictionary
    {
        public EditorResources()
            : base()
        {
            InitializeComponent();
        }
    }
}
using System;
using System.ComponentModel;
using System.Windows;
using Microsoft.Windows.Design.Metadata;
using Microsoft.Windows.Design.PropertyEditing;
using Microsoft.Win32;

namespace CustomControlLibrary.Design
{
    public class FileBrowserDialogPropertyValueEditor : DialogPropertyValueEditor
    {
        private EditorResources res = new EditorResources();

        public FileBrowserDialogPropertyValueEditor()
        {
            this.InlineEditorTemplate = res["FileBrowserInlineEditorTemplate"] as DataTemplate;
        }

        public override void ShowDialog(
            PropertyValue propertyValue,
            IInputElement commandSource)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = false;

            if (ofd.ShowDialog() == true)
            {
                propertyValue.StringValue = ofd.FileName;
            }
        }
    }
}
using System;
using System.ComponentModel;
using System.Windows;
using Microsoft.Windows.Design.Metadata;
using Microsoft.Windows.Design.PropertyEditing;

namespace CustomControlLibrary.Design
{
    internal class Metadata : IRegisterMetadata
    {
        // Called by the designer to register any design-time metadata.
        public void Register()
        {
            AttributeTableBuilder builder = new AttributeTableBuilder();

            builder.AddCustomAttributes
                ( typeof( CustomControlLibrary.DemoControl), 
                "FileName",
                PropertyValueEditor.CreateEditorAttribute(
                    typeof(FileBrowserDialogPropertyValueEditor)));

            MetadataStore.AddAttributeTable(builder.CreateTable());
        }
    }
}
<Window x:Class="WpfApplication1.Window1"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ccl="clr-namespace:CustomControlLibrary;assembly=CustomControlLibrary"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <ccl:DemoControl FileName="" />
    </Grid>
</Window>

编译代码

在三个单独的程序集内编译上面的代码示例。

编译自定义控件

  1. 在 Visual Studio 中,使用 C# 创建一个名为 CustomControlLibrary 的新 WPF 用户控件库项目。

  2. 将出现的所有“UserControl1”更改为“DemoControl”。

  3. 用上面列出的代码替换 DemoControl 类中现有的代码。

  4. 生成解决方案。

编译自定义对话框属性值编辑器

  1. 在 Visual Studio 中,向解决方案中添加一个名为 CustomControlLibrary.Design 的新 WPF 用户控件库项目。

  2. 将项目的输出路径设置为“..\CustomControlLibrary\bin\Debug\”。

  3. 从项目中删除 UserControl1.xaml 和 UserControl1.xaml.cs。

  4. 添加对下列程序集的引用。

    • Microsoft.Windows.Design

    • Microsoft.Windows.Design.Extensibility

    • Microsoft.Windows.Design.Interaction

  5. 添加对 CustomControlLibrary 项目的引用。

  6. 向项目添加名为 EditorResources 的资源字典。

  7. 将 EditorResources.xaml 中的现有 XAML 替换为前面列出的 XAML。

  8. 将名为 EditorResources 的新类添加到项目。

  9. 用上面列出的代码替换 EditorResources 中现有的代码。

  10. 向项目中添加一个名为 FileBrowserDialogPropertyValueEditor 的新类。

  11. 用上面列出的代码替换 FileBrowserDialogPropertyValueEditor 类中现有的代码。

  12. 将名为 Metadata 的新类添加到项目。

  13. 用上面列出的代码替换 Metadata 类中现有的代码。

  14. 生成解决方案。

编译测试应用程序

  1. 在 Visual Studio 中,将新的 WPF 应用程序项目添加到解决方案。

  2. 添加对 CustomControlLibrary 程序集或项目的引用。

  3. 在 Window1.xaml 的 XAML 视图中,将现有 XAML 替换为前面列出的 XAML。

  4. 在 Window1.xaml.cs 中,注释掉对 InitializeComponent 的调用。

  5. 重新生成解决方案。

  6. 在“设计”视图中,单击 DemoControl 将其选中。可能需要单击设计器顶部的信息栏以重新加载视图。

  7. 在“属性”窗口中,单击“文件名”属性旁边的按钮。

    出现“打开”对话框。

  8. 定位到某个文件,然后单击“打开”。

    文件名将显示在“属性”窗口的“文件名”属性中,FileName 属性在 XAML 视图中赋值。

请参见

参考

ItemPolicy

PrimarySelectionPolicy

其他资源

高级扩展性概念

WPF 设计器扩展性