Buscar..


Introducción

Las propiedades de dependencia son un tipo de propiedad que se extiende a una propiedad CLR. Mientras que una propiedad CLR se lee directamente de un miembro de su clase, una Propiedad de dependencia se resolverá dinámicamente al llamar al método GetValue () que su objeto obtiene a través de la herencia de la clase DependencyObject básica.

Esta sección desglosará las Propiedades de dependencia y explicará su uso tanto a nivel conceptual como a través de ejemplos de código.

Sintaxis

  • DependencyProperty.Register (nombre de cadena, Type propertyType, Type ownerType)
  • DependencyProperty.Register (nombre de cadena, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.Register (nombre de cadena, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
  • DependencyProperty.RegisterAttached (nombre de cadena, tipo propertyType, tipo ownerType)
  • DependencyProperty.RegisterAttached (nombre de cadena, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.RegisterAttached (nombre de cadena, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
  • DependencyProperty.RegisterReadOnly (nombre de cadena, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.RegisterReadOnly (nombre de cadena, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
  • DependencyProperty.RegisterAttachedReadOnly (nombre de cadena, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.RegisterAttachedReadOnly (nombre de cadena, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)

Parámetros

Parámetro Detalles
nombre La representación en String del nombre de la propiedad.
tipo de propiedad El Type de la propiedad, por ejemplo, typeof(int)
ownerType El Type de la clase en la que se define la propiedad, por ejemplo, typeof(MyControl) o typeof(MyAttachedProperties) .
typeMetadata Instancia de System.Windows.PropertyMetadata (o una de sus subclases) que define valores predeterminados, devoluciones de llamada modificadas de propiedad, FrameworkPropertyMetadata permite definir opciones de enlace como System.Windows.Data.BindingMode.TwoWay .
validateValueCallback Devolución de llamada personalizada que devuelve verdadero si el nuevo valor de la propiedad es válido, de lo contrario es falso.

Propiedades de dependencia estándar

Cuándo usar

Prácticamente todos los controles de WPF hacen un uso intensivo de las propiedades de dependencia. Una propiedad de dependencia permite el uso de muchas características de WPF que no son posibles solo con las propiedades CLR estándar, incluidas, entre otras, la compatibilidad con estilos, animaciones, enlace de datos, herencia de valores y notificaciones de cambios.

La propiedad TextBox.Text es un ejemplo simple de dónde se necesita una propiedad de dependencia estándar. Aquí, el enlace de datos no sería posible si el Text fuera una propiedad CLR estándar.

<TextBox Text="{Binding FirstName}" />

Como definir

Las propiedades de dependencia solo se pueden definir en clases derivadas de DependencyObject , como FrameworkElement , Control , etc.

Una de las formas más rápidas de crear una propiedad de dependencia estándar sin tener que recordar la sintaxis es usar el fragmento "propdp" escribiendo propdp y luego presionando Tab . Se insertará un fragmento de código que luego se puede modificar para satisfacer sus necesidades:

public class MyControl : Control
{
    public int MyProperty
    {
        get { return (int)GetValue(MyPropertyProperty); }
        set { SetValue(MyPropertyProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.
    // This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
            new PropertyMetadata(0));
}

Debe desplazarse por las diferentes partes del fragmento de código para realizar los cambios necesarios, incluida la actualización del nombre de la propiedad, el tipo de propiedad, el tipo de clase y el valor predeterminado.

Convenciones importantes

Hay algunas convenciones / reglas importantes a seguir aquí:

  1. Cree una propiedad CLR para la propiedad de dependencia. Esta propiedad se utiliza en el código subyacente de su objeto o por otros consumidores. Debe invocar GetValue y SetValue para que los consumidores no tengan que hacerlo.

  2. Nombre la propiedad de dependencia correctamente. El campo DependencyProperty debe ser public static readonly . Debe tener un nombre que se corresponda con el nombre de la propiedad CLR y termine con "Propiedad", por ejemplo, Text y TextProperty Text .

  3. No agregue lógica adicional al definidor de la propiedad CLR. El sistema de propiedades de dependencia (y XAML específicamente) no hace uso de la propiedad CLR. Si desea realizar una acción cuando cambia el valor de la propiedad, debe proporcionar una devolución de llamada a través de PropertyMetadata :

    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
            new PropertyMetadata(0, MyPropertyChangedHandler));
    
    private static void MyPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        // Use args.OldValue and args.NewValue here as needed.
        // sender is the object whose property changed.
        // Some unboxing required.
    }
    

Modo de encuadernación

Para eliminar la necesidad de especificar Mode=TwoWay en los enlaces (similar al comportamiento de TextBox.Text ), actualice el código para usar FrameworkPropertyMetadata lugar de PropertyMetadata y especifique la TextBox.Text correspondiente:

public static readonly DependencyProperty MyPropertyProperty =
    DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl), 
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

Propiedades de dependencia adjuntas

Cuándo usar

Una propiedad adjunta es una propiedad de dependencia que se puede aplicar a cualquier DependencyObject para mejorar el comportamiento de varios controles o servicios que son conscientes de la existencia de la propiedad.

Algunos casos de uso para propiedades adjuntas incluyen:

  1. Tener un elemento padre iterar a través de sus hijos y actuar sobre los niños de cierta manera. Por ejemplo, el control Grid usa las Grid.Row Grid.Column Grid.Row , Grid.Column , Grid.RowSpan y Grid.ColumnSpan para organizar los elementos en filas y columnas.
  2. Agregar elementos visuales a controles existentes con plantillas personalizadas, por ejemplo, agregar marcas de agua a cuadros de texto vacíos en toda la aplicación sin tener que subclasificar TextBox .
  3. Proporcionar un servicio o característica genérica a algunos o todos los controles existentes, por ejemplo, ToolTipService o FocusManager . Estos se conocen comúnmente como comportamientos adjuntos .
  4. Cuando se requiere la herencia del árbol visual, por ejemplo, similar al comportamiento de DataContext .

Esto demuestra aún más lo que está sucediendo en el caso de uso de Grid :

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <Label Grid.Column="0" Content="Your Name:" />
    <TextBox Grid.Column="1" Text="{Binding FirstName}" />
</Grid>

Grid.Column no es una propiedad que exista en Label o TextBox . Más bien, el control de Grid examina sus elementos secundarios y los organiza de acuerdo con los valores de las propiedades adjuntas.

Como definir

Continuaremos usando Grid para este ejemplo. La definición de Grid.Column se muestra a continuación, pero se excluye DependencyPropertyChangedEventHandler por brevedad.

public static readonly DependencyProperty RowProperty =
    DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid),
        new FrameworkPropertyMetadata(0, ...));

public static void SetRow(UIElement element, int value)
{
    if (element == null)
        throw new ArgumentNullException("element");

    element.SetValue(RowProperty, value);
}

public static int GetRow(UIElement element)
{
    if (element == null)
        throw new ArgumentNullException("element");

    return ((int)element.GetValue(RowProperty));
}

Debido a que las propiedades adjuntas se pueden adjuntar a una amplia variedad de elementos, no se pueden implementar como propiedades CLR. Un par de métodos estáticos se introduce en su lugar.

Por lo tanto, a diferencia de las propiedades de dependencia estándar, las propiedades adjuntas también se pueden definir en clases que no se derivan de DependencyObject .

Las mismas convenciones de nomenclatura que se aplican a las propiedades de dependencia regulares también se aplican aquí: la propiedad de dependencia RowProperty tiene los métodos correspondientes GetRow y SetRow .

Advertencias

Como se documenta en MSDN :

Aunque la herencia de valor de propiedad puede parecer que funciona para propiedades de dependencia no adjuntas, el comportamiento de herencia para una propiedad no asociada a través de ciertos límites de elementos en el árbol de tiempo de ejecución no está definido. Siempre use RegisterAttached para registrar propiedades donde especifique Herencias en los metadatos.

Propiedades de dependencia de solo lectura

Cuándo usar

Una propiedad de dependencia de solo lectura es similar a una propiedad de dependencia normal, pero está estructurada para no permitir que su valor se establezca desde fuera del control. Esto funciona bien si tiene una propiedad que es meramente informativa para los consumidores, por ejemplo, IsMouseOver o IsKeyboardFocusWithin .

Como definir

Al igual que las propiedades de dependencia estándar, una propiedad de dependencia de solo lectura debe definirse en una clase que se derive de DependencyObject .

public class MyControl : Control
{
    private static readonly DependencyPropertyKey MyPropertyPropertyKey = 
        DependencyProperty.RegisterReadOnly("MyProperty", typeof(int), typeof(MyControl),
            new FrameworkPropertyMetadata(0));

    public static readonly DependencyProperty MyPropertyProperty = MyPropertyPropertyKey.DependencyProperty;

    public int MyProperty
    {
        get { return (int)GetValue(MyPropertyProperty); }
        private set { SetValue(MyPropertyPropertyKey, value); }
    }
}

Las mismas convenciones que se aplican a las propiedades de dependencia regulares también se aplican aquí, pero con dos diferencias clave:

  1. DependencyProperty se obtiene de un DependencyPropertyKey private .
  2. El establecedor de propiedades CLR está protected o es private lugar de public .

Tenga en cuenta que el MyPropertyPropertyKey pasa MyPropertyPropertyKey y no MyPropertyProperty al método SetValue . Debido a que la propiedad se definió como de solo lectura, cualquier intento de usar SetValue en la propiedad debe usarse con una sobrecarga que recibe DependencyPropertyKey ; de lo contrario, se InvalidOperationException una InvalidOperationException .



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow