4

OnPropertyChanged有没有办法为使用集合中“子实体”属性的计算属性触发某种事件?

一个小例子:

我有一个带有显示客户属性的 DataGrid 的简单 WPF 应用程序。我正在使用 Entity Framework 5,CodeFirst 方法,所以我使用自己的 INotifyPropertyChanged 实现手动编写了我的类。

public partial class Customer : INotifyPropertyChanged
{
    private string _firstName;
    public virtual string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            OnPropertyChanged("FirstName");
            OnPropertyChanged("FullName");
        }
    }

    private string _lastName;
    public virtual string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            OnPropertyChanged("LastName");
            OnPropertyChanged("FullName");
        }
    }

    public virtual ICollection<Car> Cars { get; set; }
    public virtual ICollection<Invoice> Invoices { get; set; }

    ...
}

现在在同一个类中,我创建了 3 个计算属性:

    public string FullName
    {
        get { return (FirstName + " " + LastName).Trim(); }
    }

    public int TotalCars
    {
        get
        {
            return Cars.Count();
        }
    }

    public int TotalOpenInvoices
    {
        get
        {
            if (Invoices != null)
                return (from i in Invoices
                        where i.PayedInFull == false
                        select i).Count();
            else return 0;
        }
    }

FullNameDataGrid 中自动更新,因为我正在调用OnPropertyChanged("FullName");

我找到了一个 INotifyCollectionChanged 实现的示例,我可能可以使用它来自动更新TotalCars在 ICollection 中添加或删除某些内容时:http: //www.dotnetfunda.com/articles/article886-change-notification-for-objects-和-collections.aspx

但是,当ICollection ( ) 中OnPropertyChange("TotalOpenInvoices")的属性 ( ) 发生变化时触发的最佳方法是什么?PayedInFullInvoices

在 Invoice 类中做类似的事情OnPropertyChanged("Customer.TotalOpenInvoices");似乎并不能解决问题...... :)

4

2 回答 2

3

您是否可以控制收藏中的内容?如果这样做,您可以在 Invoice 对象上创建一个 Parent 属性,并将其添加到集合中时,将父级设置为您的 Customer。然后,当 PaidInFull 被设置时,运行您的 Customer.OnPropertyChanged("TotalOpenInvoices") 或调用 Customer 对象上的方法来重新计算您的发票。

在 C# 和 .Net 中强制执行父子关系

于 2012-11-06T19:43:27.460 回答
1

这假定 Invoice 和 Customer 都实现了 IPropertyChanged。只需将您的集合更改为 ObservableCollection,然后观察 CollectionChanged 属性。

添加新发票时,将事件处理程序连接到该发票的 PropertyChanged 事件。从集合中删除项目时,删除该事件处理程序。

然后,只需在 TotalOpenInvoices 属性上调用 NotifyPropertyChanged 函数。

例如(未完全测试,但应该很接近):

发票

public class Invoice : INotifyPropertyChanged
    {

        private bool payedInFull = false;
        public bool PayedInFull
        {
            get { return payedInFull; }
            set
            {
                payedInFull = value;
                NotifyPropertyChanged("PayedInFull");
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }

顾客

public class Customer : INotifyPropertyChanged
{
    public Customer()
    {
        this.Invoices.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Invoices_CollectionChanged);
    }

    ObservableCollection<Invoice> Invoices 
    {
        get;
        set;
    }

    public int TotalOpenInvoices
    {
        get
        {
            if (Invoices != null)
                return (from i in Invoices
                        where i.PayedInFull == false
                        select i).Count();
            else return 0;
        }
    }


    void Invoices_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        foreach (Invoice invoice in e.NewItems)
        {
            invoice.PropertyChanged += new PropertyChangedEventHandler(invoice_PropertyChanged);
            NotifyPropertyChanged("TotalOpenInvoices");
        }

        foreach (Invoice invoice in e.OldItems)
        {
            invoice.PropertyChanged -= new PropertyChangedEventHandler(invoice_PropertyChanged);
            NotifyPropertyChanged("TotalOpenInvoices");
        }
    }

    void invoice_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "PayedInFull")
            NotifyPropertyChanged("TotalOpenInvoices");
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}

请注意,每个类都可以抽象为实现 INotifyPropertyChanged 的​​单个类,例如 ViewModelBase 类,但这不是本示例所必需的。

于 2012-11-06T20:31:55.180 回答