Saturday, August 6, 2011

Silverlight - Dependency property CLR wrapper setter/getter not executed

Several Silverlight developers raise this as issue when they first start implementing dependency properties in their custom controls in Silverlight. While developing custom controls when there is a need to expose a property that is target of some binding, animation ...., developers will end up in creating a dependency property of some specific type. For details on dependency properties, refer to the msdn documentation.

It is the CLR wrapper which is exposed in such a way that the values are get from or set to the dependency property identifier. The basic thumb rule for creating a dependency property is the hosting class should inherit from DependencyObject. DependencyObject is the one which stores and evaluates the value of dependency properties. DependencyObject exposes the GetValue() and SetValue() methods for storing and retrieving the values of related dependency properties. Hence the CLR wrappers will hold the GetValue() and SetValue() methods in their getter and setter respectively.

Any XAML binding expressions will be specified to the exposed CLR wrapper for binding values to the related dependency property. Ok, now think of a situation where we need to place some manipulation logic when the value of the dependency property is set or changes. When similar case arise for plain CLR properties, we'll obviously place the manipulation logic in the setter of the property. If we try to do the same in dependency property - CLR wrapper, we'll end up in the method not getting called as the CLR wrapper setter won't get executed. Actually the XAML processing engine is capable of interacting with the Silverlight property system directly and get or set the value of the related dependency property with the help of DependencyObject.

Hence if at all you want to have the logic executed when the value of dependency property changes, stuff it in the PropertyChangedCallback of the property metadata. Following is a brief sample on this.

Snippet: (Dependency property with PropertyChangedCallback)

public class MyCustomControl : Control
{
    public MyCustomControl()
    {
        this.DefaultStyleKey = typeof(MyCustomControl);
    }

    #region Dependency property with PropertyChangedCallback

    public string DisplayMessage
    {
        get
        {
            return (string)GetValue(DisplayMessageProperty);
        }
        set
        {
            SetValue(DisplayMessageProperty, value);

        }
    }

    public static readonly DependencyProperty DisplayMessageProperty =
        DependencyProperty.Register("DisplayMessage", typeof(string), typeof(MyCustomControl), new PropertyMetadata(string.Empty, OnDisplayMessageChanged));

    private static void OnDisplayMessageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // Value change manipulation logic goes here......
    }

    #endregion
}


Placing additional logic in the CLR wrappers other than GetValue() and SetValue() should be avoided to eradicate any discrepancies.

References
http://msdn.microsoft.com/en-us/library/cc221408(v=vs.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(v=vs.95).aspx

No comments:

Post a Comment

Creative Commons License
This work by Tito is licensed under a Creative Commons Attribution 3.0 Unported License.