假设我有销售价格,首付金额,首付比例和贷款金额。当用户更改任何这些属性时,需要更新其他属性以反映新值。你如何处理这种类型的无限属性变化事件?
答案 0 :(得分:4)
当需要跨多个属性进行流控制时,我将建立一个流量控制变量 - 一个布尔值 - 并且在每个被更改的属性中,我将添加一个测试,以查看我是否处于流量控制之下。
private bool controlledChange = false;
public property int MyVal1
{
set
{
_myVal1 = value;
if(!controlledChange)
{
controlledChange = true;
MyVal2 -= 1;
controlledChange = false;
}
}
}
public property int MyVal2
{
set
{
_myVal2 = value;
if(!controlledChange)
{
controlledChange = true;
MyVal1 += 1;
controlledChange = false;
}
}
}
这样,无论属性如何更改都可以启动其他属性的更改,但是当它们发生更改时,它们将不会依次启动它们自己的更改集。
如果可以使用计算结果,您还应该尽可能多地阅读这些属性,以便限制对象的更改方式。
答案 1 :(得分:2)
最简单的方法是,如果该属性确实更改,则仅提出更改事件:
public decimal SalePrice {
get{
return salePrice;
}
set {
if (salePrice != value) {
salePrice = value; // putting as first statement prevents the setter
// to be entered again ...
RaiseSalePriceChange();
// Set other properties
}
}
}
答案 2 :(得分:1)
我不确定我是否完全理解,因为我不知道你的意思是什么'无限'
这可能是用字段实际支持属性的一个很好的用例。这样,您可以在Property集上触发事件,但在内部设置一个字段,而不触发N个事件。
class MyClass
{
private string m_Name;
private int m_SomeValue;
public string Name
{
get { return m_Name; }
set
{
if (value != m_Name)
{
m_Name = value;
m_SomeValue++;
// Raise Event
}
}
}
public int SomeValue
{
get { return m_SomeValue; }
set
{
if (m_SomeValue != value)
{
m_SomeValue = value;
// Raise Event
}
}
}
答案 3 :(得分:0)
如果确实需要INotifyPropertyChanged
来通知外部对象,那么我只会集中所有内容。像这样:
private double salesPrice;
private double downPaymentAmount;
private double downPaymentPercent;
private double loanAmount;
public double SalesPrice
{
get
{
return salesPrice;
}
set
{
if (salesPrice != value)
{
salesPrice = value;
// maybe you would rather use a RecalculateForSalePriceChanged() method
RecalculateDownPaymentAmount();
RecalculateDownPaymentPercent();
RecalculateLoanAmount();
propertiesChanged();
}
}
}
public double DownPaymentAmount
{
get
{
return downPaymentAmount;
}
set
{
if (downPaymentAmount != value)
{
downPaymentAmount = value;
// see above
RecalculateDownPaymentPercent();
RecalculateLoanAmount();
RecalculateSalesPrice();
propertiesChanged();
}
}
}
public double DownPaymentPercent
{
get
{
return downPaymentPercent;
}
set
{
if (downPaymentPercent != value)
{
downPaymentPercent = value;
// see above
RecalculateDownPaymentAmount();
RecalculateLoanAmount();
RecalculateSalesPrice();
propertiesChanged();
}
}
}
public double LoanAmount
{
get
{
return loanAmount;
}
set
{
if (loanAmount != value)
{
loanAmount = value;
// see above
RecalculateDownPaymentAmount();
RecalculateDownPaymentPercent();
RecalculateSalesPrice();
propertiesChanged();
}
}
}
private void propertiesChanged()
{
RaisePropertyChanged("SalesPrice", "DownPaymentAmount", "DownPaymentPercent", "LoanAmount");
}
也许你可以用更少的方法甚至单个方法集中重新计算,但我不知道你如何计算它们。但是,在重新计算值时,您必须保留特定的顺序。 由于它们只对字段进行操作而不更改属性,因此不会有PropertyChanged-feedback-loop。
希望这会有所帮助,我没有误解你的想法。
答案 4 :(得分:0)
OP想要的是跟随
class A : INotifyPropertyChanged
{
private int field1;
public int Property1
{
get { return field1; }
set
{
field1 = value;
field2++;
RaisePropertyChanged("Property1");
RaisePropertyChanged("Property2");
}
}
private int field2;
public int Property2
{
get { return field2; }
set
{
field2 = value;
field1++;
RaisePropertyChanged("Property1");
RaisePropertyChanged("Property2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
他可能正在做的是处理他提到的每个属性的setter中的其他属性,从而导致setter的循环调用。
维杰