Dependency property re-entrancy (or: why does this work?)
c#, dependency-properties, wpf
Solution
Those callbacks are only fired if the property changed, your code does not create an infinite loop of different values.
Try this and you will get a SO exception:
private static readonly Random _random = new Random();
private static void PropBChanged(DependencyObject lDependencyObject, DependencyPropertyChangedEventArgs lDependencyPropertyChangedEventArgs)
{
((MainWindow)lDependencyObject).PropA = _random.Next().ToString();
}
private static void PropAChanged(DependencyObject lDependencyObject, DependencyPropertyChangedEventArgs lDependencyPropertyChangedEventArgs)
{
((MainWindow)lDependencyObject).PropB = _random.Next().ToString();
}
Problem
Put simply, I can create 2 dependency properties in a WPF control and put code in each property change notification to change the other property (i.e `PropA` change sets `PropB` and `PropB` change sets `PropA`). I would expect this to disappear up its own backside but WPF seems to handle it nicely. That's actually very handy for my purposes but I can't find this behaviour documented anywhere. So what's going on? Does the WPF dependency property change notification system guard against reentrancy? Representative code follows: XAML: ``` <Window x:Class="WPFReentrancy1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <TextBox Text="{Binding PropB, UpdateSourceTrigger=PropertyChanged}"/> </Grid> </Window> ``` Code behind: ``` public partial class MainWindow : Window { public string PropA { get { return (string)GetValue(PropAProperty); } set { SetValue(PropAProperty, value); } } public static readonly DependencyProperty PropAProperty = DependencyProperty.Register("PropA", typeof (string), typeof (MainWindow),new UIPropertyMetadata("0", PropAChanged)); public string PropB { get { return (string)GetValue(PropBProperty); } set { SetValue(PropBProperty, value); } } public static readonly DependencyProperty PropBProperty = DependencyProperty.Register("PropB", typeof (string), typeof (MainWindow), new UIPropertyMetadata("", PropBChanged)); private static void PropBChanged(DependencyObject lDependencyObject, DependencyPropertyChangedEventArgs lDependencyPropertyChangedEventArgs) { ((MainWindow) lDependencyObject).PropA = (string) lDependencyPropertyChangedEventArgs.NewValue; } private static void PropAChanged(DependencyObject lDependencyObject, DependencyPropertyChangedEventArgs lDependencyPropertyChangedEventArgs) { ((MainWindow) lDependencyObject).PropB = double.Parse((string) lDependencyPropertyChangedEventArgs.NewValue).ToString("0.000"); } public MainWindow() { InitializeComponent(); DataContext = this; PropA = "1.123"; } } ```