Clases XAML y personalizadas para WPFXAML and Custom Classes for WPF

XAML tal como se implementa en marcos de Common Language Runtime (CLR) admite la capacidad de definir una clase o estructura personalizada en cualquier lenguaje de Common Language Runtime (CLR) y, a continuación, tener acceso a esa clase mediante el marcado XAML.XAML as implemented in common language runtime (CLR) frameworks supports the ability to define a custom class or structure in any common language runtime (CLR) language, and then access that class using XAML markup. Puede usar una mezcla de tipos definidos por Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) y sus tipos personalizados dentro del mismo archivo de marcado, normalmente asignando los tipos personalizados a un prefijo de espacio de nombres de XAML.You can use a mixture of Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF)-defined types and your custom types within the same markup file, typically by mapping the custom types to a XAML namespace prefix. En este tema se describen los requisitos que debe satisfacer una clase personalizada para que se pueda usar como elemento XAML.This topic discusses the requirements that a custom class must satisfy to be usable as a XAML element.

Clases personalizadas en aplicaciones o ensambladosCustom Classes in Applications or Assemblies

Las clases personalizadas que se usan en XAML pueden definirse de dos maneras distintas: dentro del código subyacente o de otro código que genera la aplicación primaria de Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF), o como una clase en un ensamblado independiente, como una aplicación ejecutable o DLL usado como una biblioteca de clases.Custom classes that are used in XAML can be defined in two distinct ways: within the code-behind or other code that produces the primary Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) application, or as a class in a separate assembly, such as an executable or DLL used as a class library. Cada uno de estos enfoques tiene ventajas y desventajas determinadas.Each of these approaches has particular advantages and disadvantages.

  • La ventaja de crear una biblioteca de clases es que cualquiera de esas clases personalizadas puede compartirse entre muchas posibles aplicaciones diferentes.The advantage of creating a class library is that any such custom classes can be shared across many different possible applications. Una biblioteca independiente también facilita que las versiones de las aplicaciones sean más fáciles de controlar, y simplifica la creación de una clase donde el uso previsto de la clase es como un elemento raíz en una página XAML.A separate library also makes versioning issues of applications easier to control, and simplifies creating a class where the intended class usage is as a root element on a XAML page.

  • La ventaja de definir las clases personalizadas en la aplicación consiste en que esta técnica es relativamente ligera, y minimiza los problemas de implementación y pruebas que se encuentran al especificar ensamblados independientes además del ejecutable principal de la aplicación.The advantage of defining the custom classes in the application is that this technique is relatively lightweight and minimizes the deployment and testing issues encountered when you introduce separate assemblies beyond the main application executable.

  • Si se define en el mismo ensamblado o en uno diferente, las clases personalizadas deben asignarse entre el espacio de nombres CLR y el espacio de nombres XML para usarlo en XAML como elementos.Whether defined in the same or different assembly, custom classes need to be mapped between CLR namespace and XML namespace in order to be used in XAML as elements. Vea Espacios de nombres y asignación de espacios de nombres XAML para WPF.See XAML Namespaces and Namespace Mapping for WPF XAML.

Requisitos para una clase personalizada como elemento XAMLRequirements for a Custom Class as a XAML Element

Para permitir la creación de instancias como elementos de objeto, la clase debe cumplir los requisitos siguientes:In order to be able to be instantiated as an object element, your class must meet the following requirements:

  • La clase personalizada debe ser pública y admitir un constructor público predeterminado (sin parámetros).Your custom class must be public and support a default (parameterless) public constructor. (Vea en la siguiente sección las notas relativas a las estructuras).(See following section for notes regarding structures.)

  • Su clase personalizada no debe ser una clase anidada.Your custom class must not be a nested class. Las clases anidadas y el "punto" en su sintaxis de uso de CLR general interfieren con otras características de WPFWPF o XAML como las propiedades adjuntas.Nested classes and the "dot" in their general CLR usage syntax interfere with other WPFWPF and/or XAML features such as attached properties.

Además de permitir la sintaxis de elemento de objeto, su definición del objeto también debe habilitar la sintaxis de elemento de propiedad para cualquier otra propiedad pública que admita el objeto como el tipo de valor.In addition to enabling object element syntax, your object definition also enables property element syntax for any other public properties that take that object as the value type. Esto se debe a que ahora es posible crear instancias de un objeto como un elemento de objeto y a que puede rellenar el valor de elemento de propiedad de dicha propiedad.This is because the object can now be instantiated as an object element and can fill the property element value of such a property.

EstructurasStructures

Las estructuras que se definen como tipos personalizados siempre se pueden construir en XAML en WPFWPF . Esto se debe a que los compiladores de CLR crean implícitamente un constructor sin parámetros para una estructura que inicializa todos los valores de propiedad a sus valores predeterminados.Structures that you define as custom types are always able to be constructed in XAML in WPFWPF .This is because the CLR compilers implicitly create a parameterless constructor for a structure that initializes all property values to their defaults. En algunos casos, no es deseable para una estructura el comportamiento predeterminado de construcción o el uso de elementos de objeto.In some cases, the default construction behavior and/or object element usage for a structure is not desirable. Esto se puede deber a que la estructura está pensada para rellenar valores y funcionar, desde el punto de vista conceptual, como una unión, cuyos valores contenidos pueden tener interpretaciones mutuamente excluyentes, por lo que ninguna de sus propiedades se podría establecer.This might be because the structure is intended to fill values and function conceptually as a union, where the values contained might have mutually exclusive interpretations and thus none of its properties are settable. Un WPFWPF ejemplo de este tipo de estructura GridLengthes.A WPFWPF example of such a structure is GridLength. Generalmente, tales estructuras deberían implementar un convertidor de tipos para que los valores se puedan expresar en forma de atributo y usar las convenciones de cadena que crean las diferentes interpretaciones o modos de los valores de la estructura.Generally, such structures should implement a type converter such that the values can be expressed in attribute form, using string conventions that create the different interpretations or modes of the structure's values. La estructura también debe exponer un comportamiento similar para la construcción del código a través de un constructor sin parámetros.The structure should also expose similar behavior for code construction through a non-parameterless constructor.

Requisitos para las propiedades de una clase personalizada como atributos XAMLRequirements for Properties of a Custom Class as XAML Attributes

Las propiedades deben hacer referencia a un tipo por valor (como un primitivo) o usar una clase para el tipo que tiene un constructor sin parámetros o un convertidor de tipos dedicado al que un procesador XAML puede tener acceso.Properties must reference a by-value type (such as a primitive), or use a class for type that has either a parameterless constructor or a dedicated type converter that a XAML processor can access. En la implementación XAML de CLR, los procesadores XAML encuentran tales convertidores a través de la compatibilidad nativa con primitivas de lenguaje TypeConverterAttribute o a través de la aplicación de a un tipo o miembro en definiciones de tipo de respaldo.In the CLR XAML implementation, XAML processors either find such converters through native support for language primitives, or through application of TypeConverterAttribute to a type or member in backing type definitions

De manera alternativa, la propiedad puede hacer referencia a un tipo de clase abstracta o a una interfaz.Alternatively, the property may reference an abstract class type, or an interface. Para las clases abstractas o las interfaces, la expectativa del análisis de XAML es que el valor de propiedad debe rellenarse con instancias de clase prácticas que implementen la interfaz, o con instancias de tipos derivadas de la clase abstracta.For abstract classes or interfaces, the expectation for XAML parsing is that the property value must be filled with practical class instances that implement the interface, or instances of types that derive from the abstract class.

Las propiedades se pueden declarar en una clase abstracta, pero solo se pueden establecer en las clases prácticas derivadas de la clase abstracta.Properties can be declared on an abstract class, but can only be set on practical classes that derive from the abstract class. Esto se debe a que la creación del elemento de objeto para la clase requiere un constructor sin parámetros público en la clase.This is because creating the object element for the class at all requires a public parameterless constructor on the class.

Sintaxis de atributo con convertidor de tiposTypeConverter Enabled Attribute Syntax

Si proporciona un convertidor de tipos dedicado, con atributos, en el nivel de clase, la conversión de tipos aplicada habilita la sintaxis de atributo para cualquier propiedad que necesita crear instancias de ese tipo.If you provide a dedicated, attributed type converter at the class level, the applied type conversion enables attribute syntax for any property that needs to instantiate that type. Un convertidor de tipos no habilita el uso de elementos de objeto del tipo; solo la presencia de un constructor sin parámetros para ese tipo habilita el uso de elementos de objeto.A type converter does not enable object element usage of the type; only the presence of a parameterless constructor for that type enables object element usage. Por consiguiente, las propiedades habilitadas con convertidor de tipos, en general, no se usan en sintaxis de propiedad, a menos que el propio tipo admita también la sintaxis de elemento de objeto.Therefore, properties that are type-converter enabled are generally speaking not usable in property syntax, unless the type itself also supports object element syntax. La excepción consiste en que se puede especificar una sintaxis de elemento de propiedad, pero el elemento de propiedad debe contener una cadena.The exception to this is that you can specify a property element syntax, but have the property element contain a string. Ese uso es realmente equivalente a un uso de la sintaxis de atributo, y dicho uso no es común a menos que sea necesario un control de espacio en blanco más sólido del valor del atributo.That usage is really essentially equivalent to an attribute syntax usage, and such a usage is not common unless there is a need for more robust white-space handling of the attribute value. Por ejemplo, lo siguiente es un uso de elemento de propiedad que toma una cadena y el uso de atributo equivalente:For example, the following is a property element usage that takes a string, and the attribute usage equivalent:

<Button>Hallo!
  <Button.Language>
    de-DE
  </Button.Language>
</Button>
<Button Language="de-DE">Hallo!</Button>

Ejemplos de propiedades en las que se permite la sintaxis de atributo, pero la sintaxis de elementos de propiedad que contiene un elemento de objeto no se permite Cursor a través de XAML son varias propiedades que toman el tipo.Examples of properties where attribute syntax is allowed but property element syntax that contains an object element is disallowed through XAML are various properties that take the Cursor type. La Cursor clase tiene un convertidor CursorConverterde tipos dedicado, pero no expone un constructor sin parámetros, por lo Cursor que la propiedad solo se puede establecer a través de la sintaxis Cursor de atributo, aunque el tipo real sea un tipo de referencia.The Cursor class has a dedicated type converter CursorConverter, but does not expose a parameterless constructor, so the Cursor property can only be set through attribute syntax even though the actual Cursor type is a reference type.

Convertidores de tipo por propiedadPer-Property Type Converters

De manera alternativa, la propia propiedad puede declarar un convertidor de tipos en el nivel de propiedad.Alternatively, the property itself may declare a type converter at the property level. Esto habilita un "minilenguaje" que crea instancias de objetos del tipo de la propiedad insertada, procesando los valores de cadena entrantes del atributo como entrada para ConvertFrom una operación basada en el tipo adecuado.This enables a "mini language" that instantiates objects of the type of the property inline, by processing incoming string values of the attribute as input for a ConvertFrom operation based on the appropriate type. Normalmente esto se realiza para proporcionar un descriptor de acceso adecuado, y no como único medio para habilitar el establecimiento de una propiedad en XAML.Typically this is done to provide a convenience accessor, and not as the sole means to enable setting a property in XAML. Sin embargo, también es posible usar convertidores de tipos para los atributos en los que desea utilizar tipos CLR existentes que no proporcionan un constructor sin parámetros o un convertidor de tipos con atributos.However, it is also possible to use type converters for attributes where you want to use existing CLR types that do not supply either a parameterless constructor or an attributed type converter. Los ejemplos de WPFWPF la API son ciertas propiedades que toman CultureInfo el tipo.Examples from the WPFWPF API are certain properties that take the CultureInfo type. En este caso, WPFWPF usaba el tipo de marco CultureInfo de Microsoft .net existente para mejorar la compatibilidad y los escenarios de migración que se usaban en versiones anteriores de CultureInfo marcos de trabajo, pero el tipo no admitía el constructores o conversión de tipo de nivel de tipo que se va a usar como un valor de propiedad XAML directamente.In this case, WPFWPF used the existing Microsoft .NET Framework CultureInfo type to better address compatibility and migration scenarios that were used in earlier versions of frameworks, but the CultureInfo type did not support the necessary constructors or type-level type conversion to be usable as a XAML property value directly.

Siempre que exponga una propiedad que se pueda usar en XAML, en particular si es un creador de controles, deberá considerar la posibilidad de respaldar esa propiedad con una propiedad de dependencia.Whenever you expose a property that has a XAML usage, particularly if you are a control author, you should strongly consider backing that property with a dependency property. Esto es especialmente cierto si usa la implementación existente Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) del procesador XAML, ya que puede mejorar el rendimiento mediante la DependencyProperty copia de seguridad.This is particularly true if you use the existing Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) implementation of the XAML processor, because you can improve performance by using DependencyProperty backing. Una propiedad de dependencia expondrá para la propiedad las características del sistema de propiedades que los usuarios esperan de una propiedad accesible a través de XAML.A dependency property will expose property system features for your property that users will come to expect for a XAML accessible property. Esto incluye características tales como la animación, el enlace de datos y la compatibilidad con estilos.This includes features such as animation, data binding, and style support. Para obtener más información, vea Propiedades de dependencia personalizadas y Carga de XAML y propiedades de dependencia.For more information, see Custom Dependency Properties and XAML Loading and Dependency Properties.

Escribir y asignar atributos a un convertidor de tiposWriting and Attributing a Type Converter

En ocasiones, tendrá que escribir una clase TypeConverter derivada personalizada para proporcionar la conversión de tipos para el tipo de propiedad.You occasionally will need to write a custom TypeConverter derived class to provide type conversion for your property type. Para obtener instrucciones sobre cómo derivar de y crear un convertidor de tipos que pueda admitir los TypeConverterAttributeusos de XAML y cómo aplicar, vea clases TypeConverter y XAML.For instructions on how to derive from and create a type converter that can support XAML usages, and how to apply the TypeConverterAttribute, see TypeConverters and XAML.

Requisitos para la sintaxis de atributo del controlador de eventos XAML en los eventos de una clase personalizadaRequirements for XAML Event Handler Attribute Syntax on Events of a Custom Class

Para que se pueda usar como un evento CLR, el evento se debe exponer como un evento público en una clase que admita un constructor sin parámetros o en una clase abstracta en la que se pueda tener acceso al evento en las clases derivadas.To be usable as a CLR event, the event must be exposed as a public event on a class that supports a parameterless constructor, or on an abstract class where the event can be accessed on derived classes. Para que se pueda usar de forma cómoda como un evento enrutado, el evento CLR debe add implementar remove métodos y explícitos, que agregan y quitan Controladores para la firma de eventos CLR y reenvían AddHandler esos controladores a y RemoveHandler modalidades.In order to be used conveniently as a routed event, your CLR event should implement explicit add and remove methods, which add and remove handlers for the CLR event signature and forward those handlers to the AddHandler and RemoveHandler methods. Estos métodos agregan o quitan controladores del almacén del controlador de eventos enrutados en la instancia a la que está asociado el evento.These methods add or remove the handlers to the routed event handler store on the instance that the event is attached to.

Nota

Es posible registrar controladores directamente para eventos enrutados mediante AddHandlery para no definir deliberadamente un evento CLR que exponga el evento enrutado.It is possible to register handlers directly for routed events using AddHandler, and to deliberately not define a CLR event that exposes the routed event. Esto no suele ser recomendable porque el evento no habilitará la sintaxis de atributo de XAML para asociar controladores, y la clase resultante ofrecerá una vista menos transparente XAML de las capacidades de ese tipo.This is not generally recommended because the event will not enable XAML attribute syntax for attaching handlers, and your resulting class will offer a less transparent XAML view of that type's capabilities.

Escribir propiedades de colecciónWriting Collection Properties

Las propiedades cuyo tipo es una colección tienen una sintaxis XAML que le permite especificar los objetos que se agregan a la colección.Properties that take a collection type have a XAML syntax that enables you to specify objects that are added to the collection. Esta sintaxis tiene dos características notables.This syntax has two notable features.

  • El objeto que es el objeto de colección no necesita especificarse en la sintaxis de elemento de objeto.The object that is the collection object does not need to be specified in object element syntax. La presencia de ese tipo de colección es implícita cuando se especifica una propiedad en XAML que toma un tipo de colección.The presence of that collection type is implicit whenever you specify a property in XAML that takes a collection type.

  • Los elementos secundarios de la propiedad de colección del marcado se procesan para convertirse en miembros de la colección.Child elements of the collection property in markup are processed to become members of the collection. Normalmente, el acceso del código a los miembros de una colección se realiza a través de métodos de lista y diccionario, tales como Add, o mediante un indexador.Ordinarily, the code access to the members of a collection is performed through list/dictionary methods such as Add, or through an indexer. Pero la sintaxis de XAML no admite métodos ni indexadores (excepción: XAML 2009 puede admitir métodos, pero el uso de XAML 2009 restringe los posibles usos de WPF. vea características del lenguaje XAML 2009).But XAML syntax does not support methods or indexers (exception: XAML 2009 can support methods, but using XAML 2009 restricts the possible WPF usages; see XAML 2009 Language Features). Las colecciones son obviamente un requisito muy común para compilar un árbol de elementos y necesita alguna manera de rellenarlas en XAML declarativo.Collections are obviously a very common requirement for building a tree of elements, and you need some way to populate these collections in declarative XAML. Por consiguiente, los elementos secundarios de una propiedad de colección se procesan agregándolos a la colección que es el valor de tipo de la propiedad de colección.Therefore, child elements of a collection property are processed by adding them to the collection that is the collection property type value.

La implementación de los servicios XAML de.NET Framework y el procesador XAML de WPF usan así la siguiente definición de lo que constituye una propiedad de colección.The .NET Framework XAML Services implementation and thus the WPF XAML processor uses the following definition for what constitutes a collection property. El tipo de propiedad de la propiedad debe implementar una de las opciones siguientes:The property type of the property must implement one of the following:

Cada uno de estos tipos de CLR tiene un método de Add, usado por el procesador XAML para agregar elementos a la colección subyacente al crear el gráfico de objetos.Each of these types in CLR has an Add method, which is used by the XAML processor to add items to the underlying collection when creating the object graph.

Nota

El procesador List XAML Dictionary no admiteIList<T> las IDictionary<TKey,TValue>interfaces y genéricas (y) para la WPFWPF detección de colecciones.The generic List and Dictionary interfaces (IList<T> and IDictionary<TKey,TValue>) are not supported for collection detection by the WPFWPF XAML processor. Sin embargo, puede usar la List<T> clase como una clase base, porque IList implementa directamente, o Dictionary<TKey,TValue> como IDictionary una clase base, porque implementa directamente.However, you can use the List<T> class as a base class, because it implements IList directly, or Dictionary<TKey,TValue> as a base class, because it implements IDictionary directly.

Al declarar una propiedad que toma una colección, tenga cuidado con el modo en el que se inicializa ese valor de propiedad en las nuevas instancias del tipo.When you declare a property that takes a collection, be cautious about how that property value is initialized in new instances of the type. Si no está implementando la propiedad como una propiedad de dependencia, es aconsejable hacer que la propiedad use un campo de respaldo que llame al constructor del tipo de colección.If you are not implementing the property as a dependency property, then having the property use a backing field that calls the collection type constructor is adequate. Si la propiedad es una propiedad de dependencia, quizá necesite inicializar la propiedad de colección como parte del constructor de tipo predeterminado.If your property is a dependency property, then you may need to initialize the collection property as part of the default type constructor. Esto se debe a que una propiedad de dependencia toma su valor predeterminado de los metadatos y, normalmente, no es conveniente que el valor inicial de una propiedad de colección sea una colección estática compartida.This is because a dependency property takes its default value from metadata, and you typically do not want the initial value of a collection property to be a static, shared collection. Debería haber una instancia de colección por cada instancia del tipo contenedor.There should be a collection instance per each containing type instance. Para obtener más información, vea Propiedades de dependencia personalizadas.For more information, see Custom Dependency Properties.

Puede implementar un tipo de colección personalizado para la propiedad de colección.You can implement a custom collection type for your collection property. Debido al tratamiento de propiedades de colección implícita, el tipo de colección personalizada no necesita proporcionar un constructor sin parámetros para que se pueda usar implícitamente en XAML.Because of implicit collection property treatment, the custom collection type does not need to provide a parameterless constructor in order to be used in XAML implicitly. Sin embargo, opcionalmente, puede proporcionar un constructor sin parámetros para el tipo de colección.However, you can optionally provide a parameterless constructor for the collection type. Esta puede ser una práctica útil.This can be a worthwhile practice. A menos que se proporcione un constructor sin parámetros, no se puede declarar explícitamente la colección como un elemento de objeto.Unless you do provide a parameterless constructor, you cannot explicitly declare the collection as an object element. Es posible que algunos autores de marcado prefieran considerar la colección explícita como una cuestión de estilo de marcado.Some markup authors might prefer to see the explicit collection as a matter of markup style. Además, un constructor sin parámetros puede simplificar los requisitos de inicialización al crear nuevos objetos que utilicen el tipo de colección como un valor de propiedad.Also, a parameterless constructor can simplify the initialization requirements when you create new objects that use your collection type as a property value.

Declarar propiedades de contenido XAMLDeclaring XAML Content Properties

El lenguaje XAML define el concepto de una propiedad de contenido de XAMLXAML.The XAML language defines the concept of a XAMLXAML content property. Cada clase que se puede usar en la sintaxis de objeto puede tener exactamente una propiedad de contenido XAML.Each class that is usable in object syntax can have exactly one XAML content property. Para declarar una propiedad para que sea la propiedad de contenido XAML de la clase, ContentPropertyAttribute aplique como parte de la definición de clase.To declare a property to be the XAML content property for your class, apply the ContentPropertyAttribute as part of the class definition. Especifique el nombre de la propiedad de contenido XAML deseada como Name en el atributo.Specify the name of the intended XAML content property as the Name in the attribute. La propiedad se especifica como una cadena por nombre, no como una construcción PropertyInfode reflexión como.The property is specified as a string by name, not as a reflection construct such as PropertyInfo.

Puede especificar una propiedad de colección para que sea la propiedad de contenido XAML.You can specify a collection property to be the XAML content property. El resultado es un uso para esa propiedad mediante la cual el elemento de objeto puede tener uno o más elementos secundarios, sin elementos de objeto de colección intermedios ni etiquetas de elemento de propiedad.This results in a usage for that property whereby the object element can have one or more child elements, without any intervening collection object elements or property element tags. Estos elementos se tratan entonces como el valor de la propiedad de contenido XAML y se agregan a la instancia de respaldo de la colección.These elements are then treated as the value for the XAML content property and added to the backing collection instance.

Algunas propiedades existentes de contenido de XAML usan el tipo de propiedad de Object.Some existing XAML content properties use the property type of Object. Esto habilita una propiedad de contenido XAML que puede tomar valores String primitivos como, así como tomar un valor de objeto de referencia único.This enables a XAML content property that can take primitive values such as a String as well as taking a single reference object value. Si sigue este modelo, el tipo será responsable de la determinación de tipo, así como del control de los tipos posibles.If you follow this model, your type is responsible for type determination as well as the handling of possible types. La razón típica para un Object tipo de contenido es admitir tanto un medio sencillo de agregar contenido de objeto como una cadena (que recibe un tratamiento de presentación predeterminado), o un medio avanzado de agregar contenido de objetos que especifica una presentación no predeterminada o datos adicionales.The typical reason for an Object content type is to support both a simple means of adding object content as a string (which receives a default presentation treatment), or an advanced means of adding object content that specifies a non-default presentation or additional data.

Serializar XAMLSerializing XAML

En determinados escenarios, como si es un creador de controles, quizá también quiera asegurarse de que cualquier representación de objeto de la que se pueda crear una instancia en XAML también pueda serializarse de nuevo al marcado equivalente de XAML.For certain scenarios, such as if you are a control author, you may also want to assure that any object representation that can be instantiated in XAML can also be serialized back to equivalent XAML markup. Los requisitos de serialización no se describen en este tema.Serialization requirements are not described in this topic. Vea Información general sobre la creación de controles y Árbol de elementos y serialización.See Control Authoring Overview and Element Tree and Serialization.

Vea tambiénSee also