10

WPF UI にバインドできる TotalPrice 計算プロパティを持つ単純なクラス Order があるとします。

public class Order : INotifyPropertyChanged
{
  public decimal ItemPrice 
  { 
    get { return this.itemPrice; }
    set 
    {
       this.itemPrice = value;
       this.RaisePropertyChanged("ItemPrice");
       this.RaisePropertyChanged("TotalPrice");
    }
  }

  public int Quantity 
  { 
    get { return this.quantity; }
    set 
    {
       this.quantity= value;
       this.RaisePropertyChanged("Quantity");
       this.RaisePropertyChanged("TotalPrice");
    }
  }

  public decimal TotalPrice
  {
    get { return this.ItemPrice * this.Quantity; }    
  }
}

TotalPrice の計算に影響するプロパティで RaisePropertyChanged("TotalPrice") を呼び出すのは良い方法ですか? TotalPrice プロパティを更新する最良の方法は何ですか? もちろん、これを行う他のバージョンは、このようにプロパティを変更することです

public decimal TotalPrice
{
    get { return this.ItemPrice * this.Quantity; } 
    protected set 
    {
        if(value >= 0) 
            throw ArgumentException("set method can be used for refresh purpose only");

    }
}

this.RaisePropertyChanged("TotalPrice"); の代わりに TotalPrice = -1 を呼び出します。他のプロパティで。より良い解決策を提案してください

どうもありがとう

4

4 に答える 4

7

別の解決策は、Robert Rossney がこの質問で提案したものです。

リンクされた読み取り専用プロパティの WPF INotifyPropertyChanged

プロパティの依存関係マップを作成できます (彼のコード サンプルを使用):

private static Dictionary<string, string[]> _DependencyMap = 
new Dictionary<string, string[]>
{
   {"Foo", new[] { "Bar", "Baz" } },
};

次に、OnPropertyChanged でこれを行います。

PropertyChanged(this, new PropertyChangedEventArgs(propertyName))
if (_DependencyMap.ContainsKey(propertyName))
{
   foreach (string p in _DependencyMap[propertyName])
   {
      PropertyChanged(this, new PropertyChangedEventArgs(p))
   }
}

属性をアタッチして、依存するプロパティを依存するプロパティに関連付けることもできます。何かのようなもの:

[PropertyChangeDependsOn("Foo")]
public int Bar { get { return Foo * Foo; } }
[PropertyChangeDependsOn("Foo")]
public int Baz { get { return Foo * 2; } }

属性の詳細はまだ実装していません。私は今それに取り掛かるほうがよい。

于 2011-01-04T17:46:27.560 に答える
4

値を変更する可能性のある他のメンバーからもこのイベントを発生させる必要があるかどうかを確認するのは問題ありませんが、実際に値を変更する場合にのみ行ってください。

これをメソッドにカプセル化できます。

private void CheckTotalPrice(decimal oldPrice)
{
    if(this.TotalPrice != oldPrice)
    {
         this.RaisePropertyChanged("TotalPrice");
    }
}

次に、他の変更メンバーからそれを呼び出す必要があります。

var oldPrice = this.TotalPrice;
// mutate object here...
this.CheckTotalPrice(oldPrice);
于 2010-02-10T10:09:24.583 に答える
2

NotifyPropertyWeaverを使用する場合 は、このコードを使用できます

public class Order : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public decimal ItemPrice { get; set; }

    public int Quantity { get; set; }

    public decimal TotalPrice
    {
        get { return ItemPrice*Quantity; }
    }
}

そして、これにコンパイルされます。

public class Order : INotifyPropertyChanged
{
    decimal itemPrice;
    int quantity;
    public event PropertyChangedEventHandler PropertyChanged;

    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public decimal ItemPrice
    {
        get { return itemPrice; }
        set
        {
            if (itemPrice != value)
            {
                itemPrice = value;
                OnPropertyChanged("TotalPrice");
                OnPropertyChanged("ItemPrice");
            }
        }
    }

    public int Quantity
    {
        get { return quantity; }
        set
        {
            if (quantity != value)
            {
                quantity = value;
                OnPropertyChanged("TotalPrice");
                OnPropertyChanged("Quantity");
            }
        }
    }

    public decimal TotalPrice
    {
        get { return ItemPrice*Quantity; }
    }
}
于 2012-02-05T09:39:36.930 に答える