#150 – An Example of Using PropertyChanged and CoerceValue Callbacks
December 9, 2010 6 Comments
The PropertyChangedCallback and CoerceValueCallback can be used to enforce relationships between properties on an object. Here’s an example, showing the relationship between BirthYear, MarriageYear and DeathYear properties on a Person object.
The BirthYear property:
public int BirthYear { get { return (int)GetValue(BirthYearProperty); } set { SetValue(BirthYearProperty, value); } } public static readonly DependencyProperty BirthYearProperty = DependencyProperty.Register("BirthYear", typeof(int), typeof(Person), new PropertyMetadata( 1900, // Default new PropertyChangedCallback(OnBirthYearChanged))); public static void OnBirthYearChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Person p = (Person)d; p.CoerceValue(DeathYearProperty); p.CoerceValue(MarriageYearProperty); }
The DeathYear property:
public int DeathYear { get { return (int)GetValue(DeathYearProperty); } set { SetValue(DeathYearProperty, value); } } // Using a DependencyProperty as the backing store for DeathYear. This enables animation, styling, binding, etc... public static readonly DependencyProperty DeathYearProperty = DependencyProperty.Register("DeathYear", typeof(int), typeof(Person), new PropertyMetadata( 1900, // Default new PropertyChangedCallback(OnDeathYearChanged), new CoerceValueCallback(CoerceDeathYear))); public static void OnDeathYearChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Person p = (Person)d; p.CoerceValue(MarriageYearProperty); } public static object CoerceDeathYear(DependencyObject d, object value) { Person p = (Person)d; int deathYear = (int)value; if (deathYear < p.BirthYear) deathYear = p.BirthYear; return deathYear; }
The MarriageYear property:
public int MarriageYear { get { return (int)GetValue(MarriageYearProperty); } set { SetValue(MarriageYearProperty, value); } } // Using a DependencyProperty as the backing store for DeathYear. This enables animation, styling, binding, etc... public static readonly DependencyProperty MarriageYearProperty = DependencyProperty.Register("MarriageYear", typeof(int), typeof(Person), new PropertyMetadata( 1900, // Default null, new CoerceValueCallback(CoerceMarriageYear))); public static object CoerceMarriageYear(DependencyObject d, object value) { Person p = (Person)d; int marriageYear = (int)value; if (marriageYear < p.BirthYear) marriageYear = p.BirthYear; if (marriageYear > p.DeathYear) marriageYear = p.DeathYear; return marriageYear; }
Pingback: #149 – Use PropertyChanged and Coercion Callbacks to Force Dependencies Between Properties « 2,000 Things You Should Know About WPF
Thanks for your Example.
Will be more helpful for freshers.
🙂
It is useful.But If you give the example as visual studio Program file,It will much better.
Is it possible to provice a list of valid values for a dependency property? And have for example Visual Studio respect that?
From the point of view of the coercion, no I don’t think so. The XAML editor should know the type of the property and complain if you provide a value that can’t be properly type converted. But it won’t know if your control only allows a subset of values supported by the type.
I managed to register a CoerceValue callback that would only accept some values. The PropertyEditor in Visual Studio reverted back to the old value if I returned null from the CoerceValue function.
Bug the XAML designer (xml view) changed the value in the XAML file. Can I prevent that?