4

OnPropertyChangedコレクション内の「子エンティティ」のプロパティを使用する計算されたプロパティに対して何らかのイベントをトリガーする方法はありますか?

小さな例:

Customer プロパティを表示する 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;
        }
    }

FullName呼び出しているため、DataGrid で自動的に更新されます。OnPropertyChanged("FullName");

TotalCarsICollection に何かが追加または削除され たときに自動更新するためにおそらく使用できる INotifyCollectionChanged 実装の例を見つけました: http://www.dotnetfunda.com/articles/article886-change-notification-for-objects- and-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 に答える