Do not include any logic in .NET property wrappers besides GetValue/SetValue calls. Property wrappers are bypassed at runtime when setting dependency properties in XAML.
The property value providers in order from highest to lowest precedence:
A few examples of dependency properties defined in a custom OwnerClass:
// An integer dependency property with an initial value 0. public static readonly DependencyProperty CounterProperty = DependencyProperty.Register("Counter", typeof(int), typeof(OwnerClass), new PropertyMetadata(0)); // A .NET property wrapper (optional). The GetValue and SetValue methods are inherited from DependencyObject. public int Counter { get { return (int)GetValue(CounterProperty); } set { SetValue(CounterProperty, value); } }
// A Boolean dependency property with an initial value true. public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.Register("IsEnabled", typeof(bool), typeof(OwnerClass), new PropertyMetadata(true)); public bool IsEnabled { get { return (bool)GetValue(IsEnabledProperty); } set { SetValue(IsEnabledProperty, value); } }
// A string dependency property with an initial value "". public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(OwnerClass), new PropertyMetadata("")); public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } }
Example: Define an attached property Row on a class CustomGrid:
namespace TestApp { public class CustomGrid : DependencyObject { public static readonly DependencyProperty RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(CustomGrid), new PropertyMetadata(0)); // Setting attached properties in XAML relies on the presence of the static Set method // such as SetRow in this example. public static void SetRow(UIElement element, int value) { element.SetValue(RowProperty, value); } public static int GetRow(UIElement element) { return (int)element.GetValue(RowProperty); } } }
Usage:
<Page x:Class="TestApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:TestApp"> <Grid> <Image local:CustomGrid.Row="1" ... /> </Grid> </Page>
Links:
You can also use attached properties as an extensibility mechanism. They enable you to add properties to instances of other classes/elements even if they are sealed.
Example: Attch the Tag property to the PlaneProjection element. The PlaneProjection element does not have a Tag property because it is not a FrameworkElement.
PlaneProjection proj = new PlaneProjection(); proj.SetValue(FrameworkElement.TagProperty, "some data"); // call DependencyObject.SetValue directly
Example: Handle property value changes. We define a Radius dependency property with a PropertyChanged callback. The callback specifies to invoke the OnRadiusChanged event every time the value of the dependency property changes:
// OnRadiusChanged is a delegate for change notifications. public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register("Radius", typeof(double), typeof(OwnerClass), new PropertyMetadata(200.0, new PropertyChangedCallback(OnRadiusChanged))); // wrapper property public double Radius { get { return (double)GetValue(RadiusProperty); } set { SetValue(RadiusProperty, value); } } // callback method // DependencyPropertyChangedEventArgs properties: // - Property - the property that has been changed // - OldValue // - NewValue private static void OnRadiusChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { // The obj parameter is an instance of the OwnerClass. You may use it to call any instance methods. OwnerClass owner = obj as OwnerClass; // ... }
Example: Clear a locally set property value using the DependencyObject's ClearValue method. You may need to do that if you want an element (here: a TextBlock) to inherit a value from a lower precedence property value provider:
// TextBlock1 is a TextBlock element. // TextBlock.FontSizeProperty is the static DependencyProperty field. TextBlock1.ClearValue(TextBlock.FontSizeProperty);