在没有INotifyPropertyChanged的情况下更改通知?(摘自Pro#WPF in C#2010)

blu*_*utt 8 .net c# data-binding wpf inotifypropertychanged

在C#2010中阅读Pro WPF时,作者写道:

"你可以为每个属性引发一个事件.在这种情况下,事件必须具有名称PropertyNameChanged(例如,UnitCostChanged).当你更改属性时,你可以触发事件."

有人可以确认此功能有效吗?我正在尝试并且无法重现这种行为(我想知道这是否有效,然后我可以尝试使用System.Reflection.Emit来创建动态类型)

编辑:我应该澄清这里的重点是实现更改通知而不实现INotifyPropertyChanged,因为这是本书的主张

这是我正在测试的POCO:

public class Employee
{
    private string _FirstName;
    public string FirstName 
    {
        get
        {
            return _FirstName;
        }
        set
        {
            if (_FirstName != value)
            {
                _FirstName = value;
                if (FirstNameChanged != null) 
                {
                    FirstNameChanged(this, new PropertyChangedEventArgs("FirstName"));
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我将它绑定到DataGrid并在后台有一个计时器每隔几秒随机更新一次FirstName属性,但DataGrid永远不会触发

<DataGrid x:Name="dgEmployees" ItemsSource="{Binding ElementName=mainWindow, Path=MyEmployees}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="FirstName" Binding="{Binding Path=FirstName}" />
        </DataGrid.Columns>
    </DataGrid>
Run Code Online (Sandbox Code Playgroud)

FirstNameChanged事件始终为null(我认为绑定引擎可能会在根据命名约定检测到它时自动订阅它).MyEmployees只是一个ObservableCollection

有人可以确认作者提到的这个功能是否确实有效,如果我犯了错误?

编辑:为了任何认为我错误解释文本的人的利益:

"您可以使用三种方法来解决此问题:

您可以使用在第4章中学习的语法使Product类中的每个属性成为依赖项属性.(在这种情况下,您的类必须从DependencyObject派生.)虽然这种方法让WPF为您完成工作(这很好) ),它在窗口中具有视觉外观的元素类中最有意义.对于像Product这样的数据类,这不是最自然的方法.

您可以为每个房产举办活动.在这种情况下,事件必须具有名称PropertyNameChanged(例如,UnitCostChanged).您可以在更改属性时触发事件.

您可以实现System.ComponentModel.INotifyPropertyChanged接口,该接口需要名为PropertyChanged的单个事件.然后,只要属性发生更改,就必须引发PropertyChanged事件,并通过将属性名称作为字符串提供来指示哪个属性已更改.当属性发生变化时,仍然由您来提升此事件,但您不需要为每个属性定义单独的事件."

Pet*_*sen 10

我会说在POCO中实现更改通知是非常有可能的,而不使用INotifyPropertyChanged或依赖属性,就像在书中声明的那样,除非我完全忽略了问题的要点.

如果您在属性值发生更改时从POCO 更改了一个名为{Propertyname}的事件,WPF绑定系统将选择该项,并更新相关绑定.

看一下这个小程序进行演示 - 这是我能想到的最简单的事情,但我想它也适用于你的情况.

XAML:

<StackPanel>
    <TextBlock Text="{Binding Name}" />
    <Button Content="Change name" Click="changeNameClick" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

代码隐藏:

public partial class Window1 : Window
{
    private SimpleObject so = new SimpleObject();

    public Window1()
    {
        InitializeComponent();

        this.so = new SimpleObject();
        so.Name = "Initial value";

        this.DataContext = so;

        var t = new DispatcherTimer(
            TimeSpan.FromSeconds(1), 
            DispatcherPriority.Normal,
            (s, e) => { this.so.Name = "Name changed at: " + DateTime.Now.ToString(); },
            Dispatcher);
    }

    private void changeNameClick(object sender, RoutedEventArgs e)
    {
        this.so.Name = "New value!!";
    }
}

public class SimpleObject
{
    private string mName = null;

    public string Name 
    {
        get { return mName; }
        set
        {
            if (mName != value)
            {
                mName = value;

                if (NameChanged != null)
                    NameChanged(this, EventArgs.Empty);
            }
        }
    }

    public event EventHandler NameChanged;
}
Run Code Online (Sandbox Code Playgroud)