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

时间:2012-11-06 19:21:38

标签: c# wpf datagrid entity inotifycollectionchanged

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

一个小例子:

我有一个简单的WPF应用程序,其中DataGrid显示了Customer属性。 我正在使用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;
        }
    }

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

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

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

在Invoice类中执行类似OnPropertyChanged("Customer.TotalOpenInvoices");的操作似乎没有办法......:)

2 个答案:

答案 0 :(得分:3)

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

Enforcing parent-child relationship in C# and .Net

答案 1 :(得分: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类,但这个示例不一定是必需的。