c# wpf xaml dependency-properties

c# - Devolución de llamada cuando la propiedad de dependencia recibe el cambio xaml



wpf dependency-properties (2)

Cuando establezco el valor de IsClosed durante el tiempo de ejecución, OnIsClosedChanged() se llama fine. Sin embargo, el Diseñador establece el valor de la propiedad pero no llama a OnIsClosedChanged() .

public static DependencyProperty IsClosedProperty = DependencyProperty.Register("IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)); public bool IsClosed { get { return (bool)this.GetValue(IsClosedProperty); } set { if ((bool)this.GetValue(IsClosedProperty) == value) return; this.SetValue(IsClosedProperty, value); OnIsClosedChanged(); } } private void OnIsClosedChanged() { _rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star); }

Obviamente IsClosed no es modificado por el Diseñador y solo IsClosedProperty recibe el cambio xaml.
Mi pregunta es: ¿cómo puedo ejecutar IsClosed después de que el valor haya sido modificado en el Diseñador? O al menos agregue algo de lógica a los cambios que no son de tiempo de ejecución.


Encontré la respuesta yo mismo ahora. ¡ValidateValueCallback está muy cerca! (como ha señalado Alex K) Pero es un método estático y no obtengo ninguna referencia a la instancia que ha sido modificada. La clave es usar PropertyChangedCallback en FrameworkPropertyMetadata, que también es un argumento pasado al método Property.Register.
Ver:

public static DependencyProperty IsClosedProperty = DependencyProperty.Register("IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnIsClosedChangedPCC))); public bool IsClosed { get { return (bool)this.GetValue(IsClosedProperty); } set { this.SetValue(IsClosedProperty, value); OnIsClosedChanged(); } } private static void OnIsClosedChangedPCC(DependencyObject d, DependencyPropertyChangedEventArgs e) { GroupBox current = (GroupBox)d; current.IsClosed = current.IsClosed; } private void OnIsClosedChanged() { _rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star); }

Eso ahora restablece IsClosedValue que activa el OnIsClosedChanged para ejecutarse.
¡Gracias por su ayuda chicos!


Debería registrar un PropertyChangedCallback con metadatos de propiedad.

La razón es que las propiedades de dependencia establecidas en XAML o por enlaces o alguna otra fuente no invocan el contenedor CLR (el método setter). El motivo se explica en el artículo de propiedades de carga y dependencia de XAML en MSDN:

Por razones de implementación, es computacionalmente menos costoso identificar una propiedad como una propiedad de dependencia y acceder al sistema de propiedad del método SetValue para establecerla, en lugar de usar el contenedor de propiedades y su configurador.

...

Debido a que la implementación actual de WPF del comportamiento del procesador XAML para la configuración de propiedad omite por completo las envolturas, no debe poner ninguna lógica adicional en las definiciones de conjunto de la envoltura para su propiedad de dependencia personalizada. Si pone esa lógica en la definición del conjunto, entonces la lógica no se ejecutará cuando la propiedad esté configurada en XAML en lugar de en código.

Tu código debería verse así:

public static readonly DependencyProperty IsClosedProperty = DependencyProperty.Register( "IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((GroupBox)o).OnIsClosedChanged())); public bool IsClosed { get { return (bool)GetValue(IsClosedProperty); } set { SetValue(IsClosedProperty, value); } } private void OnIsClosedChanged() { _rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star); }