C# 依赖属性重入(或:为什么这样做?)

C# 依赖属性重入(或:为什么这样做?),c#,wpf,dependency-properties,C#,Wpf,Dependency Properties,简单地说,我可以在WPF控件中创建两个依赖属性,并在每个属性更改通知中放置代码以更改其他属性(即PropAchangesetsPropB和PropBchangesetsPropA) 我希望这会消失在它自己的背后,但WPF似乎处理得很好。对于我来说,这实际上非常方便,但我在任何地方都找不到这种行为的记录 发生了什么事?WPF依赖属性更改通知系统是否防止重入 代表代码如下: XAML: <Window x:Class="WPFReentrancy1.MainWindow" xm

简单地说,我可以在WPF控件中创建两个依赖属性,并在每个属性更改通知中放置代码以更改其他属性(即
PropA
changesets
PropB
PropB
changesets
PropA

我希望这会消失在它自己的背后,但WPF似乎处理得很好。对于我来说,这实际上非常方便,但我在任何地方都找不到这种行为的记录

发生了什么事?WPF依赖属性更改通知系统是否防止重入

代表代码如下:

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>

只有当属性发生更改时才会触发这些回调,因为代码不会创建不同值的无限循环

尝试此操作,您将得到一个SO异常:

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();
}

没有具体的答案,但假设:考虑到WPF也会沿着元素的树和相关属性进行递归,它只是“保存”(对于具体事件)它已经传递的节点并触发通知,所以如果再次遇到它们,则跳过它们。我猜线索就在名称中!我假设不管怎样通知都会被触发,但我刚刚做了一个快速测试,似乎这就是正在发生的事情。
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();
}