Tutorial: Crear un editor de categorías
El modelo de extensibilidad para WPF Designer for Visual Studio permite crear editores personalizados para categorías de propiedades, denominados editores de categorías. Los editores de categorías ofrecen la posibilidad de proporcionar una interfaz de usuario personalizada que permite al usuario editar propiedades relacionadas pertenecientes a la misma categoría, como las propiedades relativas al texto. En este tutorial, se crea un editor de categorías que permite a los usuarios editar las propiedades relativas al texto de un control.
En este tutorial realizará las siguientes tareas:
Crear un proyecto de control personalizado de WPF.
Crear un editor de categorías que se puede usar para editar las propiedades relativas al texto de ese control.
Crear una clase que hereda de CategoryEditor y que representa el editor de categorías del control.
Crear una clase que implemente la interfaz IProvideAttributeTable para registrar el nuevo editor extendido.
Probar el editor de categorías 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
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.
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)) { Content = "In design mode"; } } } }
Establezca la ruta de acceso de salida del proyecto en "bin\".
Genere la solución.
Crear una clase para encapsular la información de propiedades
El editor de categorías que se va a crear requiere información sobre fuentes y propiedades asociadas, de modo que es preciso crear una clase que encapsule dicha información. El editor de categorías utilizará esta clase como origen de datos.
Para crear una clase que encapsule la información de propiedades de fuentes
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.
En el Explorador de soluciones, elimine el archivo CustomControl1 del proyecto CustomControlLibrary.Design.
En el Explorador de soluciones, elimine la carpeta Themes del proyecto CustomControlLibrary.Design.
Agregue una referencia a los siguientes ensamblados de WPF Designer.
Microsoft.Windows.Design.Extensibility
Microsoft.Windows.Design.Interaction
Agregue una referencia al proyecto CustomControlLibrary.
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.
Agregue al proyecto CustomControlLibrary.Design una nueva clase denominada FontList.
En el editor de código para FontList, 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.Collections.ObjectModel; using System.Windows; using System.Windows.Data; using System.Globalization; namespace CustomControlLibrary.Design { public class FontList : ObservableCollection<FontFamily> { public FontList() { foreach (FontFamily ff in Fonts.SystemFontFamilies) { Add(ff); } } } public class FontSizeList : ObservableCollection<double> { public FontSizeList() { Add(8); Add(9); Add(10); Add(11); Add(12); Add(14); Add(16); Add(18); Add(20); } } public class FontStyleConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { FontStyle fs = (FontStyle)value; return fs == FontStyles.Italic; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null) { bool isSet = (bool)value; if (isSet) { return FontStyles.Italic; } } return FontStyles.Normal; } } public class FontWeightConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { FontWeight fs = (FontWeight)value; return fs == FontWeights.Bold; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null) { bool isSet = (bool)value; if (isSet) { return FontWeights.Bold; } } return FontWeights.Normal; } } }
Crear la plantilla para el editor de categorías
El editor de categorías se crea mediante una plantilla de datos XAML. Se trata de una interfaz de usuario sencilla enlazada a varias propiedades relativas al texto.
Para crear la plantilla para el editor de categorías
Agregue al proyecto CustomControlLibrary.Design una nueva clase denominada EditorResources.
En el editor de código para EditorResources, reemplace el código generado automáticamente por el código siguiente.
namespace CustomControlLibrary.Design { using System; using System.Collections.Generic; using System.Text; using System.Windows; public partial class EditorResources : ResourceDictionary { public EditorResources() : base() { InitializeComponent(); } } }
En el menú Proyecto, haga clic en Agregar diccionario de recursos.
Asigne al archivo el nombre de EditorResources.xaml y haga clic en Agregar.
En la vista XAML de EditorResources, 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"> <Local:FontList x:Key="FontFamilyList"/> <Local:FontSizeList x:Key="FontSizeList"/> <Local:FontStyleConverter x:Key="FontStyleConverter"/> <Local:FontWeightConverter x:Key="FontWeightConverter"/> <DataTemplate x:Key="TextCategoryEditorTemplate"> <StackPanel Margin="5"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="50"/> </Grid.ColumnDefinitions> <ComboBox Grid.Column="0" Margin="2" ItemsSource="{Binding Source={StaticResource FontFamilyList}}" SelectedItem="{Binding [FontFamily].PropertyValue.Value}"/> <ComboBox Grid.Column="1" Margin="2" ItemsSource="{Binding Source={StaticResource FontSizeList}}" SelectedItem="{Binding [FontSize].PropertyValue.Value}"/> </Grid> <StackPanel Orientation="Horizontal"> <CheckBox Margin="2" Content="Bold" IsChecked="{Binding Path=[FontWeight].PropertyValue.Value, Converter={StaticResource FontWeightConverter}}"/> <CheckBox Margin="2" Content="Italic" IsChecked="{Binding Path=[FontStyle].PropertyValue.Value, Converter={StaticResource FontStyleConverter}}"/> </StackPanel> </StackPanel> </DataTemplate> </ResourceDictionary>
Compile la solución.
Encapsular la plantilla y registrar el editor de categorías
Ahora que ha creado la plantilla del editor de categorías, debe crear una clase que hereda de CategoryEditor para utilizar la plantilla como un editor personalizado y debe registrar el nuevo editor de categorías.
Para encapsular y registrar el editor de categorías
Agregue al proyecto CustomControlLibrary.Design una nueva clase denominada TextCategoryEditor.
En el editor de código para TextCategoryEditor, reemplace el código generado automáticamente por el código siguiente.
namespace CustomControlLibrary.Design { using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using Microsoft.Windows.Design.PropertyEditing; public class TextCategoryEditor : CategoryEditor { private EditorResources res = new EditorResources(); public TextCategoryEditor() { } public override bool ConsumesProperty(PropertyEntry property) { return true; } public override DataTemplate EditorTemplate { get { return res["TextCategoryEditorTemplate"] as DataTemplate; } } public override object GetImage(Size desiredSize) { return null; } public override string TargetCategory { get { return "Text"; } } } }
Agregue al proyecto CustomControlLibrary.Design una nueva clase denominada Metadata.
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), new EditorAttribute( typeof(TextCategoryEditor), typeof(TextCategoryEditor))); return builder.CreateTable(); } } } }
Compile la solución.
Probar el editor de categorías
El editor de categorías ya está completado y listo para su uso. Sólo queda probarlo. Para probar el editor de categorías, agregará al proyecto una aplicación de WPF, agregará el control personalizado a la aplicación de WPF y verá el editor de categorías en acción.
Para probar el editor de categorías
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.
Agregue una referencia al proyecto CustomControlLibrary.
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 texto que indica que 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>
Seleccione el control en la Vista de diseño.
En la ventana Propiedades, busque la categoría Text.
Debe aparecer una interfaz de usuario que permita especificar las propiedades de texto, distinta de los demás controles. Puede seleccionar un nombre y un tamaño de fuente en las listas desplegables. Puede especificar la negrita y la cursiva activando las casillas correspondientes.
Modifique las propiedades representadas en esta categoría. Observe que los cambios se reflejan en el control.
Vea también
Tareas
Tutorial: Implementar un editor de colores
Cómo: Crear un editor de valores