Compartir a través de


Tutorial: Implementar un editor de colores

El modelo de extensibilidad de WPF Designer for Visual Studio le permite crear editores de valores personalizados para propiedades en la ventana Propiedades en tiempo de diseño. Los editores pueden ser editores insertados, que permiten modificar valores directamente en la ventana Propiedades o editores extendidos, que permiten proporcionar una interfaz de usuario adicional para modificar una propiedad fuera de la ventana Propiedades. Para mostrar cómo se crea un editor extendido, en este tutorial se proporcionan los procedimientos paso a paso para crear un editor de colores para la propiedad Background de un control. Este editor extendido se abre desde un editor insertado en la ventana Propiedades.

En este tutorial realizará las siguientes tareas:

  • Crear un proyecto de control personalizado de WPF.

  • Cree un control de usuario que actuará como el editor extendido.

  • Cree un editor insertado que se pueda utilizar para modificar el valor de la propiedad en la ventana Propiedades y abrir el editor extendido.

  • Cree una clase que herede de ExtendedPropertyValueEditor que se utiliza para conectar los editores con la clase para la que desea proporcionar la edición personalizada.

  • Cree una clase que implemente la interfaz IProvideAttributeTable para registrar el nuevo editor extendido.

  • Pruebe el editor extendido en tiempo de diseño.

Requisitos previos

Necesita los componentes siguientes para completar este tutorial:

  • Visual Studio 2010.

Crear el control personalizado

El primer paso consiste en crear el proyecto para el control personalizado. El control es un botón simple con poco código en tiempo de diseño, que utiliza el método GetIsInDesignMode para implementar un comportamiento en tiempo de diseño.

Para crear el control personalizado

  1. Cree un nuevo proyecto de biblioteca de controles personalizados de WPF en Visual C# denominado CustomControlLibrary.

    El código de CustomControl1 se abre en el editor de código.

  2. En el editor de código para CustomControl1, reemplace el código del espacio de nombres CustomControlLibrary por el siguiente código:

    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. Establezca la ruta de acceso de los resultados del proyecto en "bin\".

  4. Genere la solución.

Crear el control de usuario para el editor extendido

El control que creó en el procedimiento anterior es el control al que va a asociar el editor de colores personalizado. En este procedimiento creará otro control de usuario que actuará como el editor extendido.

Para crear un control de usuario que actuará como el editor extendido

  1. Agregue a la solución un nuevo proyecto de biblioteca de controles personalizados de WPF en Visual C# denominado CustomControlLibrary.Design.

    El código de CustomControl1 se abre en el editor de código.

  2. En el Explorador de soluciones, elimine el archivo CustomControl1 del proyecto CustomControlLibrary.Design.

  3. Agregue una referencia a los siguientes ensamblados de WPF Designer.

    • Microsoft.Windows.Design.Extensibility

    • Microsoft.Windows.Design.Interaction

  4. Agregue una referencia al proyecto CustomControlLibrary.

  5. Establezca la ruta de acceso de salida del proyecto en ".. \CustomControlLibrary\bin\". De este modo, el ensamblado del control y el ensamblado de metadatos permanecen en la misma carpeta, lo que permite que los diseñadores detecten los metadatos.

  6. Agregue al proyecto CustomControlLibrary.Design una nueva clase denominada ColorsList.

  7. En el editor de código para ColorsList, reemplace el código generado automáticamente por el código siguiente.

    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. Agregue un nuevo elemento de control de usuario (WPF) denominado ColorsListControl al proyecto CustomControlLibrary.Design.

    El código para ColorsListControl.xaml se abre en el diseñador.

  9. En la vista XAML de ColorsListControl.xaml, reemplace el XAML generado automáticamente por el XAML siguiente.

        <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. En el Explorador de soluciones, expanda ColorsListControl.xaml y abra ColorsListControl.xaml.cs.

  11. En el editor de código para ColorsListControl, reemplace el código generado automáticamente por el código siguiente.

    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. Compile la solución.

  13. Vuelva a cargar ColorsListControl.xaml en el diseñador y deberá ver aparecer la interfaz de usuario del editor extendido en la Vista de diseño.

Crear las plantillas para el editor de colores

El editor insertado del editor de colores es menos complejo que el editor extendido y se puede crear con una plantilla de datos XAML. También creará una plantilla de datos para el editor extendido que especifica que se use el control de usuario que creó en el procedimiento anterior.

Para crear la plantilla para el editor de colores

  1. Agregue al proyecto CustomControlLibrary.Design una nueva clase denominada EditorResources.

  2. En el editor de código para EditorResources, reemplace el código generado automáticamente por el código siguiente.

    namespace ExtendedEditorNamespace
    {
        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.Windows;
        public partial class EditorResources : ResourceDictionary {
            public EditorResources()
                : base()
            {
                InitializeComponent();
            }
        }
    }
    
  3. En el menú Proyecto, haga clic en Agregar diccionario de recursos.

  4. Asigne al archivo el nombre de EditorResources.xaml y haga clic en Agregar.

    El código para EditorResources.xaml se abre en el diseñador.

  5. En la vista XAML de EditorResources.xaml, reemplace el XAML generado automáticamente por el XAML siguiente.

        <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. Compile la solución.

Encapsular las plantillas y registrar los editores

El trabajo más difícil ya ha terminado. Ahora que ha creado las plantillas del editor extendido y del editor insertado para el editor de colores, puede crear una clase que los encapsula y después los registra con el control personalizado.

Para encapsular y registrar los editores

  1. Agregue al proyecto CustomControlLibrary.Design una nueva clase denominada BrushExtendedEditor.

  2. En el editor de código para BrushExtendedEditor, reemplace el código generado automáticamente por el código siguiente.

    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. Agregue al proyecto CustomControlLibrary.Design una nueva clase denominada Metadata.

  4. En el editor de código para Metadata, reemplace el código generado automáticamente por el código siguiente.

    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. Compile la solución.

Probar el editor de colores

Acaba de terminar de crear el editor de colores. Lo único que queda ahora es probarlo. Para probar el editor agregará a la solución un proyecto de aplicación de WPF y agregará el control personalizado. A continuación cambiará el fondo en la ventana Propiedades y verá el nuevo editor en acción.

Para probar el editor de colores

  1. Agregue a la solución un nuevo proyecto de aplicación de WPF en Visual C# denominado DemoApplication.

    MainWindow.xaml se abre en WPF Designer.

  2. Agregue una referencia al proyecto CustomControlLibrary.

  3. En la vista XAML de MainWindow.xaml, reemplace el XAML generado automáticamente por el XAML siguiente. Este XAML agrega una referencia al espacio de nombres CustomControlLibrary y agrega el control personalizado CustomControl1. El botón aparece en la Vista de diseño con un fondo rojo, que indica que el control se encuentra en modo de diseño. Si el botón no aparece, es posible que tenga que hacer clic en la barra de información situada en la parte superior del diseñador para volver a cargar la vista.

        <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. Seleccione el control en la Vista de diseño.

  5. En la ventana Propiedades, haga clic en el botón de lista desplegable situado junto a la propiedad Background. Se mostrará un editor de colores visual en lugar de la lista predeterminada de colores.

  6. Seleccione un color del editor. El color de fondo del control personalizado cambiará a ese color.

Vea también

Tareas

Tutorial: Implementar un editor de valores insertados

Cómo: Crear un editor de valores

Otros recursos

Crear editores personalizados

Extensibilidad de WPF Designer