Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Windows Presentation Foundation (WPF) proporciona un conjunto de servicios que se pueden usar para ampliar la funcionalidad de la propiedad de un tipo. En conjunto, estos servicios se conocen como el sistema de propiedades de WPF. Una propiedad respaldada por el sistema de propiedades de WPF se conoce como una propiedad de dependencia. En esta introducción se describe el sistema de propiedades de WPF y las funcionalidades de una propiedad de dependencia, incluido cómo usar las propiedades de dependencia existentes en XAML y en el código. En esta introducción también se presentan aspectos especializados de las propiedades de dependencia, como los metadatos de la propiedad de dependencia y cómo crear su propia propiedad de dependencia en una clase personalizada.
Prerrequisitos
En este artículo se da por supuesto el conocimiento básico del sistema de tipos de .NET y la programación orientada a objetos. Para seguir los ejemplos de este artículo, ayuda a comprender XAML y a saber cómo escribir aplicaciones WPF. Para obtener más información, vea Tutorial: Creación de una aplicación WPF con .NET.
Propiedades de dependencia y propiedades CLR
Las propiedades de WPF normalmente se exponen como propiedades estándar de .NET. Puede interactuar con estas propiedades en un nivel básico y nunca saber que se implementan como una propiedad de dependencia. Sin embargo, familiarizarse con algunas o todas las características del sistema de propiedades de WPF le ayudará a aprovechar esas características.
El propósito de las propiedades de dependencia es proporcionar una manera de calcular el valor de una propiedad en función del valor de otras entradas, como:
- Propiedades del sistema, como temas y preferencias de usuario.
- Mecanismos de determinación de propiedades en el momento oportuno, como vinculación de datos y animaciones o guiones gráficos.
- Plantillas de varios usos, como recursos y estilos.
- Valores conocidos a través de relaciones de padre-hijo con otros elementos en el árbol de elementos.
Además, una propiedad de dependencia puede proporcionar:
- Validación independiente.
- Valores predeterminados.
- Funciones de retorno que monitorizan los cambios en otras propiedades.
- Un sistema que puede coaccionar los valores de propiedad basándose en la información en tiempo de ejecución.
Las clases derivadas pueden cambiar algunas características de una propiedad existente reemplazando los metadatos de una propiedad de dependencia, en lugar de invalidar la implementación real de las propiedades existentes o crear nuevas propiedades.
En la referencia del SDK, puede identificar una propiedad de dependencia mediante la presencia de una sección Información de propiedad de dependencia en la página de referencia administrada de esa propiedad. La sección Información de la propiedad de dependencia incluye un vínculo al DependencyProperty campo de identificador de esa propiedad de dependencia. También incluye la lista de opciones de metadatos para esa propiedad, información de invalidación por clase y otros detalles.
Las propiedades de dependencia respaldan las propiedades clR
Las propiedades de dependencia y el sistema de propiedades de WPF amplían la funcionalidad de propiedades proporcionando un tipo que respalda una propiedad, como alternativa al patrón estándar de respaldo de una propiedad con un campo privado. El nombre de este tipo es DependencyProperty. El otro tipo importante que define el sistema de propiedades de WPF es DependencyObject, que define la clase base que puede registrar y poseer una propiedad de dependencia.
Esta es una terminología que se usa habitualmente:
Propiedad de dependencia, que es una propiedad respaldada por una DependencyProperty.
Identificador de propiedad de dependencia, que es una
DependencyPropertyinstancia obtenida como un valor devuelto al registrar una propiedad de dependencia y, a continuación, se almacena como un miembro estático de una clase. Muchas de las API que interactúan con el sistema de propiedades de WPF usan el identificador de propiedad de dependencia como parámetro.CLR "wrapper", que son las implementaciones
getysetpara la propiedad. Estas implementaciones incorporan el identificador de propiedad de dependencia usándolo en las llamadas de GetValue y SetValue. De este modo, el sistema de propiedades WPF proporciona la copia de seguridad de la propiedad.
En el ejemplo siguiente se define la IsSpinning propiedad de dependencia para mostrar la relación del DependencyProperty identificador con la propiedad que respalda.
public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register(
"IsSpinning", typeof(bool),
typeof(MainWindow)
);
public bool IsSpinning
{
get => (bool)GetValue(IsSpinningProperty);
set => SetValue(IsSpinningProperty, value);
}
Public Shared ReadOnly IsSpinningProperty As DependencyProperty =
DependencyProperty.Register("IsSpinning", GetType(Boolean), GetType(MainWindow))
Public Property IsSpinning As Boolean
Get
Return GetValue(IsSpinningProperty)
End Get
Set(value As Boolean)
SetValue(IsSpinningProperty, value)
End Set
End Property
La convención de nomenclatura de la propiedad y su campo auxiliar DependencyProperty es importante. El nombre del campo siempre es el nombre de la propiedad, con el sufijo Property anexado. Para obtener más información sobre esta convención y los motivos de esta convención, consulte Propiedades de dependencia personalizadas.
Establecer valores de propiedad
Puedes establecer propiedades en el código o en XAML.
Establecimiento de valores de propiedad en XAML
En el ejemplo XAML siguiente se establece el color de fondo de un botón en rojo. El valor de cadena para el atributo XAML es convertido por el analizador XAML de WPF en un tipo WPF. En el código generado, el tipo WPF es un Color mediante un SolidColorBrush.
<Button Content="I am red" Background="Red"/>
XAML admite varios formularios de sintaxis para establecer propiedades. La sintaxis que se va a usar para una propiedad determinada depende del tipo de valor que usa una propiedad y de otros factores, como la presencia de un convertidor de tipos. Para obtener más información sobre la sintaxis XAML para establecer propiedades, consulta XAML en WPF y sintaxis XAML con más detalle.
En el ejemplo XAML siguiente se muestra otro fondo de botón que usa la sintaxis del elemento de propiedad en lugar de la sintaxis de atributo. En lugar de establecer un color sólido simple, el XAML establece la propiedad de botón Background en una imagen. Un elemento representa esa imagen y un atributo del elemento anidado especifica el origen de la imagen.
<Button Content="I have an image background">
<Button.Background>
<ImageBrush ImageSource="stripes.jpg"/>
</Button.Background>
</Button>
Establecimiento de propiedades en el código
Establecer valores de propiedad de dependencia en el código suele ser simplemente una llamada a la set implementación expuesta por clR "wrapper":
Button myButton = new();
myButton.Width = 200.0;
Dim myButton As New Button With {
.Width = 200.0
}
Obtener un valor de propiedad es básicamente una llamada a la get implementación de "envoltorio":
double whatWidth = myButton.Width;
Dim whatWidth As Double = myButton.Width
También puede llamar directamente a las API del sistema de propiedades GetValue y SetValue. Llamar directamente a las API es adecuada para algunos escenarios, pero normalmente no cuando se usan propiedades existentes. Normalmente, los contenedores son más cómodos y proporcionan una mejor exposición de la propiedad para las herramientas de desarrollo.
Las propiedades también se pueden establecer en XAML y, a continuación, se puede acceder a ellas más adelante en el código, a través del código subyacente. Para obtener más información, consulta Code-behind and XAML in WPF (Código subyacente y XAML en WPF)
Funcionalidad proporcionada por una propiedad dependiente
A diferencia de una propiedad respaldada por un campo, una propiedad de dependencia extiende la funcionalidad de una propiedad . A menudo, la funcionalidad agregada representa o admite una de estas características:
Recursos
Puede establecer un valor de propiedad de dependencia haciendo referencia a un recurso. Normalmente, los recursos se especifican como el Resources valor de propiedad de un elemento raíz de página o de la aplicación, ya que estas ubicaciones ofrecen un acceso cómodo al recurso. En este ejemplo, definimos un SolidColorBrush recurso:
<StackPanel.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
</StackPanel.Resources>
Ahora que se define el recurso, podemos hacer referencia al recurso para proporcionar un valor para la Background propiedad :
<Button Background="{DynamicResource MyBrush}" Content="I am gold" />
En XAML de WPF, puedes usar una referencia de recursos estáticos o dinámicos. Se hace referencia a este recurso en particular como dynamicResource.
Nota:
Los recursos se tratan como un valor local, lo que significa que si establece otro valor local, eliminará la referencia de recursos. Para obtener más información, consulte Precedencia de valores de propiedad de dependencia.
Vinculación de datos
Una propiedad de dependencia puede hacer referencia a un valor a través del enlace de datos. La vinculación de datos funciona a través de una sintaxis de extensión de marcado específica en XAML, o el objeto Binding en código. Con el enlace de datos, la determinación del valor de propiedad final se aplaza hasta el tiempo de ejecución, en cuyo momento se obtiene el valor de un origen de datos.
En el ejemplo siguiente se establece la Content propiedad de un Button, mediante un enlace declarado en XAML. El enlace usa un contexto de datos heredado y un XmlDataProvider origen de datos (no se muestra). El enlace especifica la propiedad de origen dentro del origen de datos por XPath.
<Button Content="{Binding Source={StaticResource TestData}, XPath=test[1]/@text}"/>
Nota:
Los enlaces se tratan como un valor local, lo que significa que si establece otro valor local, eliminará el enlace. Para obtener más información, consulte Precedencia de valores de propiedad de dependencia.
Las propiedades de dependencia, o la clase DependencyObject, no admiten de forma nativa la notificación de cambios en el valor de la propiedad de origen INotifyPropertyChanged para las operaciones de enlace de datos DependencyObject. Para obtener más información sobre cómo crear propiedades para usarlas en el enlace de datos que pueden notificar cambios en un destino de enlace de datos, consulte Introducción al enlace de datos.
Estilos
Los estilos y las plantillas son razones atractivas para usar las propiedades de dependencia. Los estilos son especialmente útiles para establecer propiedades que definen la interfaz de usuario de la aplicación. Normalmente, los estilos se definen como recursos en XAML. Los estilos interactúan con el sistema de propiedades porque normalmente contienen "establecedores" para determinadas propiedades y "desencadenadores" que cambian un valor de propiedad en función del valor en tiempo de ejecución de otra propiedad.
En el ejemplo siguiente se crea un estilo simple, que se definiría dentro de un Resources diccionario (no se muestra). A continuación, ese estilo se aplica directamente a la Style propiedad de un Button. La propiedad establecida dentro del estilo configura la propiedad Background para que el elemento estilizado Button sea verde.
<Style x:Key="GreenButtonStyle">
<Setter Property="Control.Background" Value="Green"/>
</Style>
<Button Style="{StaticResource GreenButtonStyle}" Content="I am green"/>
Para obtener más información, vea Aplicar estilos y plantillas.
Animaciones
Las propiedades de dependencia se pueden animar. Cuando se ejecuta una animación aplicada, el valor animado tiene mayor prioridad que cualquier otro valor de propiedad, incluido un valor local.
En el ejemplo siguiente se anima la propiedad Background de una Button. Técnicamente, la sintaxis del elemento de propiedad establece un valor en blanco SolidColorBrush como el Background, y la propiedad Color del SolidColorBrush se anima.
<Button Content="I am animated">
<Button.Background>
<SolidColorBrush x:Name="AnimBrush"/>
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="AnimBrush"
Storyboard.TargetProperty="(SolidColorBrush.Color)"
From="Blue" To="White" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Para obtener más información sobre cómo animar propiedades, consulte Introducción a las animaciones y Introducción a los storyboard
Sobrescrituras de metadatos
Puede cambiar comportamientos específicos de una propiedad de dependencia reemplazando sus metadatos al derivar de la clase que registró originalmente la propiedad de dependencia. La invalidación de metadatos se apoya en el DependencyProperty identificador y no requiere volver a implementar la propiedad. El sistema de propiedades controla el cambio de metadatos de forma nativa. Cada clase puede contener metadatos individuales para todas las propiedades heredadas de clases base, por tipo.
En el ejemplo siguiente se invalidan los metadatos de una DefaultStyleKey propiedad de dependencia. La invalidación de metadatos para esta propiedad de dependencia determinada forma parte de un patrón de implementación para crear controles que pueden usar estilos predeterminados de temas.
public class SpinnerControl : ItemsControl
{
static SpinnerControl() => DefaultStyleKeyProperty.OverrideMetadata(
typeof(SpinnerControl),
new FrameworkPropertyMetadata(typeof(SpinnerControl))
);
}
Public Class SpinnerControl
Inherits ItemsControl
Shared Sub New()
DefaultStyleKeyProperty.OverrideMetadata(GetType(SpinnerControl), New FrameworkPropertyMetadata(GetType(SpinnerControl)))
End Sub
End Class
Para obtener más información sobre cómo invalidar o acceder a metadatos para propiedades de dependencia, consulte Invalidación de metadatos para una propiedad de dependencia.
Herencia de valores de propiedad
Un elemento puede heredar el valor de una propiedad de dependencia de su elemento primario en el árbol de objetos.
Nota:
El comportamiento de herencia de valores de propiedad no está habilitado globalmente para todas las propiedades de dependencia, ya que el tiempo de cálculo de la herencia afecta al rendimiento. La herencia de valores de propiedad normalmente solo está habilitada en escenarios que sugieren aplicabilidad. Puede comprobar si una propiedad de dependencia se hereda consultando la sección Información de propiedades de dependencia en la referencia del SDK.
En el ejemplo siguiente se muestra un enlace que incluye la DataContext propiedad para especificar el origen del enlace. Por lo tanto, los enlaces de objetos secundarios no necesitan especificar el origen y pueden usar el valor heredado de DataContext en el objeto primario StackPanel . O bien, un objeto secundario puede especificar directamente su propio DataContext o un Source en el Binding, sin utilizar el valor heredado.
<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource TestData}}">
<Button Content="{Binding XPath=test[2]/@text}"/>
</StackPanel>
Para obtener más información, vea Herencia de valores de propiedad.
Integración del diseñador de WPF
Los controles personalizados con propiedades implementadas como propiedades de dependencia se integran bien con WPF Designer para Visual Studio. Un ejemplo es la capacidad de editar propiedades de dependencia directas y adjuntas en la ventana Propiedades . Para obtener más información, consulte Información general sobre la creación de controles.
Precedencia del valor de la propiedad de dependencia
Cualquiera de las entradas basadas en propiedades dentro del sistema de propiedades de WPF puede establecer el valor de una propiedad de dependencia. La prioridad del valor de propiedad de dependencia existe para que los distintos escenarios de cómo las propiedades obtengan sus valores interactúan de forma predecible.
Nota:
La documentación del SDK a veces usa el término "valor local" o "valor establecido localmente" al analizar las propiedades de dependencia. Un valor establecido localmente es un valor de propiedad que se establece directamente en una instancia de objeto en el código o como atributo de elemento en XAML.
En el ejemplo siguiente se incluye un estilo que se aplica a la Background propiedad de cualquier botón, pero especifica un botón con una propiedad establecida Background localmente. Técnicamente, ese botón tiene su Background propiedad establecida dos veces, aunque solo se aplica un valor, el valor con la prioridad más alta. Un valor establecido localmente tiene la prioridad más alta, excepto para una animación en ejecución, que no existe aquí. Por lo tanto, el segundo botón usa el valor establecido localmente para la Background propiedad, en lugar del valor de establecedor de estilo. El primer botón no tiene ningún valor local u otro valor con mayor prioridad que un establecedor de estilo, por lo que usa el valor de establecedor de estilo para la Background propiedad .
<StackPanel>
<StackPanel.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Orange"/>
</Style>
</StackPanel.Resources>
<Button>I am styled orange</Button>
<Button Background="Pink">I am locally set to pink (not styled orange)</Button>
</StackPanel>
¿Por qué existe la precedencia de las propiedades de dependencia?
Los valores establecidos localmente tienen prioridad sobre los valores de establecedor de estilo, que admiten el control local de las propiedades del elemento. Para obtener más información, consulte Precedencia de valores de propiedad de dependencia.
Nota:
Una serie de propiedades definidas en elementos WPF no son propiedades de dependencia, ya que las propiedades de dependencia normalmente se implementaron solo cuando se requería una característica del sistema de propiedades de WPF. Entre las características se incluyen el enlace de datos, el estilo, la animación, la compatibilidad con valores predeterminados, la herencia, las propiedades adjuntas y la invalidación.
Más información sobre las propiedades de dependencia
Es posible que los desarrolladores de componentes o desarrolladores de aplicaciones deseen crear su propia propiedad de dependencia para agregar funcionalidades, como el enlace de datos o la compatibilidad con estilos, o la compatibilidad con la invalidación y la coerción de valores. Para obtener más información, consulte Propiedades de dependencia personalizadas.
Considere la posibilidad de que las propiedades de dependencia sean propiedades públicas, accesibles o detectables por cualquier llamador con acceso a una instancia. Para obtener más información, consulte Seguridad de propiedades de dependencia.
Una propiedad adjunta es un tipo de propiedad que admite una sintaxis especializada en XAML. Una propiedad adjunta a menudo no tiene una correspondencia 1:1 con una propiedad de Common Language Runtime y no es necesariamente una propiedad de dependencia. El propósito principal de una propiedad adjunta es permitir que los elementos secundarios notifiquen los valores de propiedad a un elemento primario, aunque el elemento primario y el elemento secundario no incluyan esa propiedad como parte de las listas de miembros de clase. Un escenario principal es habilitar un elemento secundario para informar a los elementos primarios sobre cómo presentarlos en la interfaz de usuario. Para obtener ejemplos, vea Dock y Left. Para obtener más información, consulte Introducción a las propiedades adjuntas.
Consulte también
.NET Desktop feedback