I’d like to highlight one more feature that is available in Silverlight if you use my code snippets.
Those who watched the value coercion video might have glimpsed the following enum within the FrameworkPropertyMetadata.cs code file:
[Flags]
public enum FrameworkPropertyMetadataOptions : int
{
None = 0x0,
AffectsMeasure = 0x1,
AffectsArrange = 0x2,
AffectsParentMeasure = 0x4,
AffectsParentArrange = 0x8,
}
This enum provides a limited subset of the metadata options that are available in WPF. Specifically, these are the options used with dependency properties that affect layout.
How do metadata options work?
If you are not familiar with these metadata options, here’s a quick rundown… In WPF, a dependency property on a framework element can be registered with one or more metadata options. This is done by combining the desired flags using a bitwise “OR” and then passing that value into the appropriate DependencyProperty.Register() overload.
As an example, the Width property on FrameworkElement is registered with the AffectsMeasure option. As such, the property engine will take care of invalidating measure on the target element whenever the Width property changes.
The other layout options work pretty much the same way. The AffectsArrange flag will cause InvalidateArrange() to be called on the target element when the property changes. The AffectsParentMeasure and AffectsParentArrange flags will cause InvalidateMeasure() and InvalidateArrange() to be called, respectively, on the target element’s parent.
It’s All About Portability
In Silverlight, there is no native mechanism for registering a property to affect measure or arrange. As such, you typically register a PropertyChangedCallback on the property and then explicitly call InvalidateMeasure() and/or InvalidateArrange() within your callback.
If you use my snippets, you can follow the exact same approach in Silverlight that you would use in WPF for properties that affect layout. My FrameworkPropertyMetadata class will take care of the necessary layout invalidations. So a property that affects measure could be declared in Silverlight using my ‘dp s1’ snippet, as follows:
#region VerticalExtent /// <summary> /// VerticalExtent Dependency Property /// </summary> public static readonly DependencyProperty VerticalExtentProperty = DependencyProperty.Register("VerticalExtent", typeof(double), typeof(MyControl), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure)); /// <summary> /// Gets or sets the VerticalExtent property. This dependency property /// indicates the vertical extent of the control. /// </summary> public double VerticalExtent { get { return (double)GetValue(VerticalExtentProperty); } set { SetValue(VerticalExtentProperty, value); } } #endregion
What about the other WPF metadata options?
There are several metadata options in WPF that are not included in my Silverlight enum. These are intentionally excluded because they either cannot be supported outside the native Silverlight framework (e.g., the property engine would need to be modified to support the NotDataBindable option) or they simply don’t make sense in Silverlight (e.g., Silverlight does not currently support direct rendering via an OnRender() override, so I don’t provide an AffectsRender flag).
I hope you find the provided layout metadata options handy!
Cheers!
Dr. WPF
Thanks for this, I really liked it and will use it. One question though – might be unrelated – : is there a way to specify when registering/creating a Dependency Property (in Silverlight) that it should bind two way by default like in WPF? AFAIK, there’s no documented/known way to to this. Can this limitation get a workaround?
Sincerely,
Stefan
Hi Stefan,
In WPF, the BindingExpressionBase class enables binding-related metadata options. Unfortunately, the BindingExpressionBase class in Silverlight is an empty class… it exists purely for compatibility reasons. It does not provide (nor is there elsewhere) analogous support for the BindsTwoWayByDefault option. As such, this is one of the flags that would require fundamental changes to the Silverlight property/binding engine.
Who knows… maybe we’ll get it sometime in the future. For now, we just have to be explicit when creating our bindings in Silverlight.
Cheers,
-dw