Поделиться через


Практическое руководство. Создание редактора значений свойств диалогового окна

В следующем примере кода показано, как реализовать пользовательский редактор значений свойств диалогового окна для Конструктор WPF для Visual Studio. Полное решение см. в примере "Dialog Property Value Editor" в разделе WPF Designer Extensibility Samples веб-сайта корпорации Майкрософт. 

Пример

В данном разделе показано, как создать редактор значений свойств диалогового окна, отображающий диалоговое окно с открытым файлом при щелчке пользовательского свойства FileName в окне "Свойства".

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.Interaction"
                    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;

// The ProvideMetadata assembly-level attribute indicates to designers
// that this assembly contains a class that provides an attribute table. 
[assembly: ProvideMetadata(typeof(CustomControlLibrary.Design.Metadata))]
namespace CustomControlLibrary.Design
{
    // Container for any general design-time metadata to initialize.
    // Designers look for a type in the design-time assembly that 
    // implements IProvideAttributeTable. If found, designers instantiate 
    // this class and access its AttributeTable property automatically.
    internal class Metadata : IProvideAttributeTable 
    {
        // Accessed by the designer to register any design-time metadata.
        public AttributeTable AttributeTable
        {
            get 
            {
                AttributeTableBuilder builder = new AttributeTableBuilder();

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

                return builder.CreateTable();
            }
        }
    }
}
<Window x:Class="WpfApplication1.MainWindow"
    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="MainWindow" Height="300" Width="300">
    <Grid>
        <ccl:DemoControl FileName="" />
    </Grid>
</Window>

Компиляция кода

Скомпилируйте код из предыдущего примера в трех отдельных сборках.

Компиляция пользовательского элемента управления

  1. В Visual Studio создайте новый проект библиотеки пользовательских элементов управления WPF на языке C# с именем CustomControlLibrary.

  2. Измените все вхождения "UserControl1" на "DemoControl".

  3. Замените существующий код в классе DemoControl на код, представленный выше.

  4. Выполните построение решения.

Компиляция пользовательского редактора значений свойств диалогового окна

  1. В Visual Studio добавьте к решению новый проект библиотеки пользовательских элементов управления WPF с именем CustomControlLibrary.Design.

  2. Задайте выходной путь проекта как ".. \CustomControlLibrary\bin\Debug\".

  3. Удалите из проекта файлы UserControl1.xaml и UserControl1.xaml.cs.

  4. Добавьте ссылки на следующие сборки:

    • Microsoft.Windows.Design.Extensibility

    • Microsoft.Windows.Design.Interaction

  5. Добавьте ссылку на проект CustomControlLibrary.

  6. Добавьте к проекту словарь ресурсов с именем EditorResources.

  7. Замените существующий код XAML в файле EditorResources.xaml на приведенный выше код XAML.

  8. Добавьте к проекту новый класс с именем EditorResources.

  9. Замените существующий код класса "EditorResources" на код, представленный выше.

  10. Добавьте к проекту новый класс с именем FileBrowserDialogPropertyValueEditor.

  11. Замените существующий код в классе FileBrowserDialogPropertyValueEditor на код, представленный выше.

  12. Добавьте в проект новый класс с именем Metadata.

  13. Замените существующий код в классе Metadata на код, представленный выше.

  14. Выполните построение решения.

Компиляция тестового приложения

  1. В Visual Studio добавьте к решению новый проект приложения WPF.

  2. Добавьте ссылку на сборку или проект CustomControlLibrary.

  3. В представлении XAML для файла MainWindow.xaml замените существующий код на код, представленный выше.

  4. В файле MainWindow.xaml.cs установите метки комментария для вызова InitializeComponent.

  5. Перестройте решение.

  6. В представлении конструктора выберите элемент управления DemoControl. При необходимости щелкните панель информации в верхней части конструктора, чтобы перезагрузить представление.

  7. В окне "Свойства" нажмите кнопку рядом со свойством FileName.

    Откроется диалоговое окно Открыть.

  8. Выберите файл и нажмите кнопку Открыть.

    Имя файла отображается в свойстве FileName окна "Свойства" и свойство FileName назначается в представлении XAML.

См. также

Ссылки

ItemPolicy

PrimarySelectionPolicy

Другие ресурсы

Дополнительные понятия расширяемости

Расширяемость среды конструктора WPF

WPF Designer Extensibility Samples