[英]C# MVVM Calculating Total
我需要根據選定的價格和數量計算交易價值。 怎么能
以下是我的ViewModel:
class ViewModel : ViewModelBase
{
public Trade Trade
{
get { return _trade; }
set { SetField(ref _trade, value, () => Trade); }
} private Trade _trade;
public decimal TradeValue
{
get { return Trade.Amount * Trade.Price; }
}
}
ViewModelBase繼承INotifyPropertyChanged並包含SetField()
以下是貿易類:
public class Trade : INotifyPropertyChaged
{
public virtual Decimal Amount
{
get { return _amount; }
set { SetField(ref _amount, value, () => Amount); }
} private Decimal _amount;
public virtual Decimal Price
{
get { return _price; }
set { SetField(ref _price, value, () => Price); }
} private Decimal _price;
......
}
我知道由於設計我的TradeValue只計算一次(當它第一次請求時),並且當金額/價格變化時UI不會更新。 實現這一目標的最佳方法是什么?
任何幫助非常感謝。
更新: INotifyPropertyChanged實現:
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
if (selectorExpression == null)
throw new ArgumentNullException("selectorExpression");
var body = selectorExpression.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The body must be a member expression");
OnPropertyChanged(body.Member.Name);
}
protected bool SetField<T>(ref T field, T value, Expression<Func<T>> selectorExpression)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(selectorExpression);
return true;
}
這兩個答案都有效,現在我不知道選擇哪一個作為最佳答案。 Luke的答案似乎更好,因為似乎只有更少的代碼重復,盡管只是監聽OnPropertyChanged事件似乎更輕量級。
這就是我通常這樣做的方式:
private bool has_inited_tradevalue_linkage = false;
public decimal TradeValue
{
get
{
if(!has_inited_tradevalue_linkage)
{
has_inited_tradevalue_linkage = true;
this.PropertyChanged += (_, e) =>
{
if(e.PropertyName.Equals("Amount") || e.PropertyName.Equals("Price"))
OnPropertyChanged("TradeValue");
};
}
return Trade.Amount * Trade.Price; }
}
這種方式鏈接是懶惰地構造的(所以你不發布沒有人感興趣的事件),並且所有的邏輯仍然包含在這個屬性中。 相反,您可以在Price
和Amount
的設置者中添加對OnPropertyChanged("TradeValue")
調用,但這對於課堂上的其他人來說有點糟糕(至少在我看來)。 我已經非常成功地使用了這種模式,以創建類似的“依賴”屬性。
另一個選擇就是專門跟蹤依賴項:
在ViewModelBase中你可以添加這個:
私人詞典> DependencyMap = new Dictionary>(); protected void AddPropertyDependency(String prop,String dependantProp){if(DependencyMap.ContainsKey(prop)){DependencyMap [prop] .Add(dependantProp); } else {DependencyMap [prop] = new List {dependantProp}; }}
然后在你的OnPropertyChanged
方法中:
protected void OnPropertyChanged(String prop)
{
var eh = PropertyChanged;
if(eh != null)
{
eh(this, new PropertyChangedEventArgs(prop);
if(DependencyMap.ContainsKey(prop))
{
foreach(var p in DependencyMap[prop])
OnPropertyChanged(p);//recursive call would allow for arbitrary dependencies
}
}
}
然后在您的類構造函數中,您只需定義屬性依賴項:
public ViewModel()
{
AddPropertyDependency("Amount", "TradeValue");
AddPropertyDependency("Price", "TradeValue");
}
這絕對是一個更通用的解決方案,大多數更改都在您的基類中。
private void UpdateValue()
{
this.Value = this.Acres * this.YieldPerAcre * this.UnitPrice;
}
public double Acres
{
get { return _cropProductionRecord.Acres; }
set
{
_cropProductionRecord.Acres = value;
OnPropertyChanged("Acres");
UpdateValue();
}
}
public double YieldPerAcre
{
get { return _cropProductionRecord.YieldPerAcre; }
set
{
_cropProductionRecord.YieldPerAcre = value;
OnPropertyChanged("YieldPerAcre");
UpdateValue();
}
}
public double UnitPrice
{
get { return _cropProductionRecord.UnitPrice; }
set
{
_cropProductionRecord.UnitPrice = value;
OnPropertyChanged("UnitPrice");
UpdateValue();
}
}
public double Value
{
get { return _cropProductionRecord.Value; }
set
{
_cropProductionRecord.Value = value;
OnPropertyChanged("Value");
}
}
在VM類的Trade屬性的set方法中,在Trade類上訂閱PropertyChanged事件。 在該事件處理程序中,為屬性TradeValue發布propertychanged。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.