WPF introduced a new concept for managing properties which is dependency properties. Dependency properties can act as standard properties, but also offer a lot more functionality, such as data binding, assignment through resources, setters in styles, and a lot more. They also allow for easy extensibility since they can be declared in different classes than the types they affect, and can be set directly from XAML. Silverlight, of course, has inherited this, yet it has a subtle difference.
In order to define a dependency property for a user control in Silverlight, suppose TestNumber of type int in the control TestControl (those are original names, aren't they?), you must do the following:
public int TestNumber { get { return (int)GetValue(TestNumberProperty); } set { SetValue(TestNumberProperty, value); } } // Using a DependencyProperty as the backing store for TestNumber. // This enables animation, styling, binding, etc... public static readonly DependencyProperty TestNumberProperty = DependencyProperty.Register("TestNumber", typeof(int), typeof(TestControl), new PropertyMetadata( new PropertyChangedCallback(TestNumberChanged)));
Looks a bit scary at first, specially if you have to remember all that whenever you want to make a new dependency property. Luckily Visual Studio ships with the propdp
code snippet that automatically creates this.
The public property ensures easy access from code to the property, so that you can treat dependency and standard properties exactly the same way. Getters and setters forward the call to the FrameworkElement functions GetValue and SetValue, which receive the property to manage.
As for the property, it is registered statically, by declaring its name, type, owner and metadata. In this last piece is where the difference with WPF relies. While WPF expects an instance of UIPropertyMetadata, which allows you to specify an on-change callback, a default value, forbid animations and a few more things, Silverlight dependency properties receive a PropertyMetadata, which allows you to specify only the callback, not default values.
Nevertheless, there is an easy workaround to supply a default value for these properties as long they are defined for a user/custom control. When you set a value for a control in XAML, the value is set after its constructor is invoked (which makes sense if you think about it). All you have to do then is set the property value in the constructor, and it doesn't matter whether it is before or after the InitializeComponent call.
In case you are wondering when the control's constructor is invoked, it is when its parent's InitializeComponent call is made. What this method does is process the XAML and create all objects specified in it, and set all fields named after the named controls with their correct values.