Пошаговое руководство. Реализация редактора цвета

Модель расширяемости для Конструктор WPF для Visual Studio позволяет создавать редакторы пользовательских значений для свойств в окне "Свойства" во время разработки. Это могут быть встроенные редакторы, которые позволяют изменять значения непосредственно в окне "Свойства", или расширенными редакторами, которые позволяют предоставлять дополнительный пользовательский интерфейс для редактирования свойств вне окна "Свойства". Для демонстрации создания расширенного редактора в данном пошаговом руководстве представлены пошаговые инструкции по созданию редактора цвета для свойства Background элемента управления. Этот расширенный редактор открывается из встроенного редактора окна "Свойства".

В данном пошаговом руководстве выполняются следующие задачи.

  • создать проект пользовательского элемента управления WPF;

  • создать пользовательский элемент управления, который будет работать как расширенный редактор;

  • создать встроенный редактор, который может использоваться для редактирования значения свойства в окне "Свойства" и открытия расширенного редактора;

  • Создание класса, производного от интерфейса ExtendedPropertyValueEditor, который используется для подключения редакторов к классу, для которого нужно предоставить функции редактирования;

  • Создайте класс, реализующий интерфейс IProvideAttributeTable, для регистрации нового расширенного редактора.

  • протестировать расширенный редактор во время разработки.

Обязательные компоненты

Ниже приведены компоненты, необходимые для выполнения данного пошагового руководства.

  • Visual Studio 2010.

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

Первым этапом является создание проекта для пользовательского элемента управления. Этот элемент управления представляет собой простую кнопку, созданную с помощью небольшого количества кода, в котором для реализации поведения во время разработки используется метод GetIsInDesignMode.

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

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

    В редакторе кода откроется код для элемента управления CustomControl1.

  2. В редакторе кода для CustomControl1 замените код в пространстве имен CustomControlLibrary следующим кодом:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    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 CustomControlLibrary
    {
        public class CustomControl1 : Button
        {
            public CustomControl1()
            {
                if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
                {
                    Background = Brushes.Red;
                }
            }
        }
    }
    
  3. Задайте выходной путь проекта как "bin\".

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

Создание пользовательского элемента управления для расширенного редактора

Элемент управления, созданный в предыдущей процедуре, является элементом управления, к которому будет присоединен настраиваемый редактор цвета. В этой процедуре предстоит создать другой пользовательский элемент управления, который будет работать как расширенный редактор.

Чтобы создать пользовательский элемент управления, который будет работать как расширенный редактор

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

    Код для CustomControl1 откроется в редакторе кода.

  2. В обозревателе решений удалите файл CustomControl1 из проекта CustomControlLibrary.Design.

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

    • Microsoft.Windows.Design.Extensibility

    • Microsoft.Windows.Design.Interaction

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

  5. Задайте выходной путь проекта как ".. \CustomControlLibrary\bin\". В этом случае сборка элемента управления и сборка метаданных будут находиться в одной папке, что обеспечит доступ к метаданным для конструкторов.

  6. Добавьте новый класс с именем ColorsList в проект CustomControlLibrary.Design.

  7. В редакторе кода для 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 CustomControlLibrary.Design
    {
        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));
                    }
                }
            }
        }
    }
    
  8. Добавьте новый пользовательский элемент управления (WPF) с именем ColorsListControl в проект CustomControlLibrary.Design.

    Код для файла ColorsListControl.xaml откроется в конструкторе.

  9. В представлении XAML для ColorsListControl.xaml замените автоматически созданный XAML-код на следующий XAML-код.

        <UserControl x:Class="CustomControlLibrary.Design.ColorsListControl"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Local="clr-namespace:CustomControlLibrary.Design" 
        xmlns:PropertyEditing="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design.Interaction"
        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>
    
  10. В обозревателе решений разверните ColorsListControl.xaml и откройте файл ColorsListControl.xaml.cs.

  11. В редакторе кода для 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 CustomControlLibrary.Design
    {
        public partial class ColorsListControl : System.Windows.Controls.UserControl
        {
            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); }
            }
    
            private void ItemsControl_Click(object sender, RoutedEventArgs e)
            {
                SelectedColor = (Color)((Button)sender).Tag;
                SelectedBrush = new SolidColorBrush(SelectedColor);
            }
        }
    }
    
  12. Выполните построение решения.

  13. Перезагрузите ColorsListControl.xaml в конструкторе, в окне должен отобразиться пользовательский интерфейс расширенного редактора.

Создание шаблонов для редактора цвета

Встроенный редактор для редактора цвета является менее сложным, чем расширенный редактор, и может создаваться с помощью шаблона данных XAML. Шаблон данных также создается для расширенного редактора, задающего использование пользовательского элемента управления, созданный в предыдущей процедуре.

Чтобы создать шаблон для редактора цвета

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

  2. В редакторе кода для класса EditorResources замените автоматически создаваемый код на следующий код.

    namespace ExtendedEditorNamespace
    {
        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.Windows;
        public partial class EditorResources : ResourceDictionary {
            public EditorResources()
                : base()
            {
                InitializeComponent();
            }
        }
    }
    
  3. В меню Проект выберите пункт Добавить словарь ресурсов.

  4. Присвойте файлу имя "EditorResources.xaml" и нажмите кнопку Добавить.

    Код для EditorResources.xaml откроется в конструкторе.

  5. В представлении XAML для EditorResources.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.Interaction"
        xmlns:Local="clr-namespace:CustomControlLibrary.Design"
        xmlns:Media="clr-namespace:System.Windows.Media;assembly=PresentationCore"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        x:Class="CustomControlLibrary.Design.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>
    
  6. Выполните построение решения.

Инкапсуляция шаблонов и регистрация редакторов

Наиболее сложные этапы завершены. Теперь, создав шаблоны расширенного и встроенного редакторов для редактора цвета, можно создать класс, инкапсулирующий их и затем регистрирующий их в пользовательском элементе управления.

Чтобы осуществить инкапсуляцию и регистрацию редакторов

  1. Добавьте новый класс с именем BrushExtendedEditor в проект CustomControlLibrary.Design.

  2. В редакторе кода для BrushExtendedEditor замените автоматически создаваемый код на следующий код.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Windows.Design.PropertyEditing;
    using System.Windows;
    
    namespace CustomControlLibrary.Design
    {
        public class BrushExtendedEditor : ExtendedPropertyValueEditor
        {
            private EditorResources res = new EditorResources();
    
            public BrushExtendedEditor()
            {
                this.ExtendedEditorTemplate = res["BrushExtendedEditorTemplate"] as DataTemplate;
                this.InlineEditorTemplate = res["BrushInlineEditorTemplate"] as DataTemplate;
            }
        }
    }
    
  3. Добавьте новый класс с именем Metadata к проекту "CustomControlLibrary.Design".

  4. В редакторе кода для класса Metadata замените автоматически создаваемый код на следующий код.

    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;
    
    // 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(CustomControl1),
                        "Background",
                        PropertyValueEditor.CreateEditorAttribute(
                            typeof(BrushExtendedEditor)));
    
                    return builder.CreateTable();
                }
            }
        }
    }
    
  5. Выполните построение решения.

Тестирование редактора цвета

Создание редактора цвета завершено. Следующий этап — тестирование редактора. Чтобы проверить редактор, следует добавить в решение проект приложения WPF и добавить созданный пользовательский элемент управления. Затем нужно будет изменить свойство Background в окне "Свойства" и посмотреть новый редактор в действии.

Чтобы протестировать редактор цвета

  1. Добавьте к решению новый проект приложения WPF на языке Visual C# с именем DemoApplication.

    Файл MainWindow.xaml будет открыт в сред. Конструктор WPF.

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

  3. В представлении XAML для MainWindow.xaml замените автоматически создаваемый код XAML на следующий код XAML. В этом коде XAML добавляется ссылка на пространство имен CustomControlLibrary и пользовательский элемент управления CustomControl1. Красный фон кнопки, отображаемой в представлении конструктора, указывает, что элемент управления находится в режиме разработки. Если кнопка не отображается, щелкните панель информации в верхней части конструктора для перезагрузки представления.

        <Window x:Class="DemoApplication.MainWindow"
        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"></my:CustomControl1>
        </Grid>
    </Window>
    
  4. В представлении "Конструктор" выделите элемент управления.

  5. В окне Свойства нажмите кнопку раскрывающегося списка свойства Background. Отобразится визуальный редактор цвета вместо списка цветов по умолчанию.

  6. Выберите цвет из редактора. Фон пользовательского элемента управления изменится на этот цвет.

См. также

Задачи

Пошаговое руководство. Реализация встроенного редактора значений

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

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

Создание пользовательских редакторов

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