control c# wpf dependency-properties

c# - control - Dependencia Propiedad WPF



control wpf (4)

He estado leyendo acerca de las propiedades de dependencia en varios libros, pero todos tienen una cosa en común, simplemente nos dicen cómo se implementan (usando static readonly DependencyProperty etc.) pero no indican la forma exacta en que funcionan desde adentro.

Quiero decir que se implementan como estáticas, pero aún se aplica a todos los objetos.
Segundo punto de confusión es propiedades adjuntas.

¿Hay algún tutorial disponible que pueda explicar todos estos conceptos de una manera fácil?


A continuación, puede ver un ejemplo muy básico de dependency property de dependency property que crea un custom control text box en el que no se permitirá el espacio significa que el usuario no puede escribir espacio en el cuadro de texto.

1) Cree una clase con el nombre de ValidatedTextBox y escriba el siguiente código en este archivo de clase:

public class ValidatedTextBox : TextBox { public ValidatedTextBox() { } public static readonly DependencyProperty IsSpaceAllowedProperty = DependencyProperty.Register("IsSpaceAllowed", typeof(bool), typeof(ValidatedTextBox)); public bool IsSpaceAllowed { get { return (bool)base.GetValue(IsSpaceAllowedProperty); } set { base.SetValue(IsSpaceAllowedProperty, value); } } protected override void OnPreviewKeyDown(KeyEventArgs e) { base.OnPreviewKeyDown(e); if (!IsSpaceAllowed && (e.Key == Key.Space)) { e.Handled = true; } } }

2) Ahora use el control anterior en su archivo .XAML

a) Agregue el espacio de nombres del cuadro de texto de control personalizado como a continuación:

xmlns:CustomControls="clr-namespace: ValidatedTextBox;assembly= ValidatedTextBox "

b) Ahora, use el cuadro de texto de control personalizado como a continuación:

<CustomControls:ValidatedTextBox IsSpaceAllowed="False" x:Name="MyTextBox" />

Creará un cuadro de texto de control personalizado que no permitirá espacio. Por lo tanto, la propiedad Básicamente Dependencia permite agregar una función, extender la función de cualquier control.


Aquí hay un tutorial sobre las propiedades de dependencia http://www.wpftutorial.net/DependencyProperties.html que explica un poco sobre cómo funcionan.

La breve explicación de por qué el objeto DependencyProperty está en un campo estático es que representa la descripción de la propiedad, no el valor de la propiedad. Cada DependencyObject tiene una asignación de los objetos DependencyProperty a sus valores.

Así es como funcionan las propiedades adjuntas. Debido a que cada DependencyObject almacena una asignación de cualquier DependencyProperty a un valor, cualquier tipo puede crear una nueva DependencyProperty y establecerla en cualquier DependencyObject existente.


Mi modelo mental de cómo funcionan las propiedades de dependencia:

Cualquier clase DependencyObject implementa dos propiedades especiales. Uno, una propiedad estática de la clase, es un diccionario de objetos DependencyProperty . Cada instancia de la clase puede buscar dentro de ese diccionario para encontrar información sobre cada Propiedad de DependencyProperty : el nombre de la propiedad, su tipo, cualquier devolución de llamada que deba llamarse cuando se obtenga y establecer, cómo participa en la herencia de la propiedad, etc. Cuando registra una propiedad de dependencia, está agregando una entrada a este diccionario.

La otra propiedad es una propiedad de instancia: es un diccionario, codificado por DependencyProperty , que contiene el valor local de cada DependencyProperty , si se ha establecido.

Los métodos SetValue y GetValue que implementas en el setter y getter de la propiedad CLR son básicamente una evaluación perezosa sobre los esteroides. En lugar de almacenar y recuperar el valor de la propiedad en un campo de respaldo, almacenan y recuperan el valor de la propiedad en el diccionario de valores.

La magia de las propiedades de dependencia está en lo que GetValue y SetValue realmente hacen.

GetValue busca el valor de la propiedad en el diccionario de valores del objeto. Si no lo encuentra, llama a GetValue en el elemento padre para obtener lo que el elemento padre cree que es el valor. Por ejemplo, cuando creas un TextBox en una Window , cualquier cosa que se vea en FontFamily del TextBox realidad está llamando a GetValue . A menos que haya establecido explícitamente la fuente, no hay ninguna entrada en su diccionario para esa propiedad. Entonces, GetValue le pregunta al elemento padre por el valor. El elemento padre puede o no tener establecido FontFamily ; si no, su llamada a GetValue devuelve el valor de su padre. Y así sucesivamente, hasta que se alcance el objeto Window y se encuentre el valor real de FontFamily .

Si establece FontFamily en el TextBox , SetValue almacena el valor en el diccionario de valores. La próxima vez que algo necesite obtener el valor de FontFamily para ese TextBox , GetValue encuentra el valor en el diccionario y lo devuelve, por lo que no es necesario que pregunte al elemento padre.

Si establece FontFamily en la Window , SetValue no solo actualiza el valor en el diccionario de valores de Window , sino que desencadena un evento de cambio de propiedad que todo lo que depende de la propiedad escucha. (Es por eso que se llaman propiedades de dependencia, recuerden). Y si la cosa que depende de la propiedad es en sí misma una propiedad de dependencia, dispara sus propios eventos de cambio de propiedad. Así es como el cambio de FontFamily en la Window cambia la fuente para cada control en la ventana y también le pide a WPF que vuelva a renderizar los controles que han cambiado.

Las propiedades adjuntas funcionan utilizando el mismo tipo de enfoque. Cualquier objeto que pueda tener propiedades adjuntas tiene un diccionario en el que se almacenan los valores de las propiedades adjuntas. Cuando configura Grid.Column en un CheckBox en XAML, solo está agregando una entrada al diccionario de CheckBox . Cuando la Grid necesita saber en qué columna está el CheckBox , busca el valor de ese diccionario. Cuando establece Grid.IsSharedSizeScope en True en un objeto, el diccionario de ese objeto contendrá una nueva propiedad: un diccionario que contiene anchos / alturas para cada SharedSizeKey .

Debo enfatizar que este es mi modelo mental. No me senté con Reflector y SetValue la implementación real de Register , GetValue y SetValue para descubrir cómo funcionan realmente. Puede que me equivoque sobre los detalles. Pero es un modelo que predice con precisión cómo se comportan estas cosas, por lo que es lo suficientemente bueno.

El concepto de almacenar valores de propiedad en diccionarios es bastante extraño para los programadores de C #. Sin embargo, es un sombrero viejo para los programadores de Python. En Python, todas las propiedades de clase, todos los objetos, de hecho, se almacenan en diccionarios, por lo que puede obtener su valor a través de los accesores de propiedades o simplemente buscándolos. Las propiedades de dependencia y las propiedades adjuntas son solo otra forma en que .NET, habiendo robado todo lo que Java tenía que valía la pena robar, ahora está saqueando Python. (O desde donde Python los saqueó). Aprender Python me ha hecho mucho mejor programador de C #; Lo recomiendo a cualquier desarrollador de C # que no lo haya hecho todavía.