WPF中PropertyChanged UpdateSourceRigger的一种奇怪行为

WPF中PropertyChanged UpdateSourceRigger的一种奇怪行为,wpf,binding,propertychanged,updatesourcetrigger,Wpf,Binding,Propertychanged,Updatesourcetrigger,我有这样一个实体: public class Person { public string Name { get; set; } public Person() { Name = "Godspeed"; } } 然后我在XAML中有三个文本框和一个按钮: <Window x:Class="WpfApplication19.MainWindow" xmlns="http://schemas.microsoft.com/win

我有这样一个实体:

public class Person
{
    public string Name { get; set; }

    public Person()
    {
        Name = "Godspeed";
    }
}
然后我在XAML中有三个文本框和一个按钮:

<Window x:Class="WpfApplication19.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication19"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:Person />
    </Window.DataContext>
    <StackPanel>
        <TextBox Text="{Binding Name,UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Text="{Binding Name,UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Text="{Binding Name,UpdateSourceTrigger=PropertyChanged}" />
        <Button Click="Button_Click">Click</Button>
    </StackPanel>
</Window>

它不会更新。所以我认为如果Person类实现INotifyPropertyChanged,这种行为是正常的,但是现在这个类没有实现接口,但是它也更新了接口。如果你有线索,请告诉我原因。谢谢。

正如您所说,您只需实现
INotifyPropertyChanged

PropertyChanged
事件在您从code设置属性时使用,并且需要将此更改反映到您的UI(UI将包含
PropertyChanged
事件,并且由于您的
UpdateSourceTrigger
将更新UI)。另一方(从UI更改)不需要任何
属性更改
,这就是您获得此行为的原因

就这样试试吧:

    public class Person : INotifyPropertyChanged
    {
            #region INotifyPropertyChanged Members

            /// <summary>
            /// Property Changed Event
            /// </summary>
            public event PropertyChangedEventHandler PropertyChanged;

            /// <summary>
            /// Property Changed
            /// </summary>
            /// <param name="propertyName"></param>
            protected void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            #endregion

    private string name;

    public string Name
    {
      get { return name; }
      set 
      {
        name = value;
        OnPropertyChanged("Name");
      }
    }

}
公共类人员:INotifyPropertyChanged
{
#区域INotifyProperty更改成员
/// 
///属性更改事件
/// 
公共事件属性更改事件处理程序属性更改;
/// 
///财产变更
/// 
/// 
受保护的无效OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
#端区
私有字符串名称;
公共字符串名
{
获取{返回名称;}
设置
{
名称=值;
不动产变更(“名称”);
}
}
}

使用此代码,当您设置名称时,将触发
PropertyChanged
事件,因此相应地更新UI:)

原因是PropertyDescriptor,请参阅以下线程, 有人问同样的问题:

这里有两个答案

我认为魔法在于装订系统的使用 PropertyDescriptor(SetValue)可能会引发一个ValueChanged- PropertyDescriptor可能是共享的,而事件是在 按对象计算)


我不在微软,但我可以证实。如果PropertyDescriptor是 用于按原样更新值,然后进行相关更改 通知会自动传播

编辑
您可以通过命名
Person
DataContext对象来验证这一点

<Window.DataContext>
    <local:Person x:Name="person"/>
</Window.DataContext>

更改三个文本框中任何一个的值后,您将进入事件处理程序OnPropertyChanged。

它不仅适用于updatesourcetrigger=propertychanged,还适用于默认(失去焦点)值。除了@Meleak所说的之外,我想指出这是一种良好的行为。ui所做的任何更改都会传播到所有绑定目标。绑定引擎希望一次将此更改传播到所有控件。如果您通过代码进行更改,而未实现INotifyPropertyChanged,则从代码进行的更改根本不会反映出来。同样,对于具有相同绑定源的所有控件。所有控件都以同步方式与此类实现一起工作。

因此,您的意思是,如果我设置propertychanged,UpdateRigger将自动更新UI,而不仅仅是对源实体进行更改?INotifyPropertyChanged接口只会触发从右后代码更改UI?就是这样,是的。基本上,UpdateRigger正在等待捕获PropertyChanged事件以刷新绑定。因为你没有在任何地方发射它,它不会触发任何更新。你明白我在这里说的意思了:PropertyChanged是用来说“嘿,UI,请刷新你自己,我变了!”:)
<Window.DataContext>
    <local:Person x:Name="person"/>
</Window.DataContext>
public MainWindow()
{
    InitializeComponent();

    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(person);
    PropertyDescriptor nameProperty = properties[0];
    nameProperty.AddValueChanged(person, OnPropertyChanged);
}
void OnPropertyChanged(object sender, EventArgs e)
{
    MessageBox.Show("Name Changed");
}