我在这里有一些课程,或多或少都相互依赖。这种关系有点像依赖树:
class A {
List<B> _bs = new List<B>();
public int ValueOfA {
get {
return _bs.Sum(p => p.ValueOfB);
}
}
class B {
List<C> _cs = new List<C>();
public int ValueOfB {
get {
return _cs.Where(p => p.ValueOfC > 1).Sum(p => p.ValuOfC);
}
}
class C {
public int ValueOfC { get; set }
}
因此,每当_bs
,_cs
或ValueOfC
发生变化时,与其相关的每个财产都应该在变更时得到通知,从而重新计算。
持续可靠地实现这一目标的最佳方法是什么?有没有机会自动完成这项工作?
答案 0 :(得分:0)
您需要在班级INotifyPropertyChanged
上实施C
。在ValueOfC
的集合中,您将触发事件:
class C : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int valueOfC;
public int ValueOfC
{
get { return valueOfC; }
set
{
valueOfC = value;
OnPropertyChanged(PropertyChanged);
}
}
protected virtual void OnPropertyChanged(PropertyChangedEventHandler handler)
{
if (handler != null)
handler(this, new PropertyChangedEventArgs("ValueOfC"));
}
}
我刚试过它,它完美无缺。
使用受保护的虚拟方法为您触发事件只是常见做法。
作为旁注,如果您希望在列表更改时执行某些操作,则可能需要考虑使用BindingList或ObservableCollection。
修改强>
我写了一个小例子来刷新整个树:
public class Bank : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private BindingList<Customer> customers = new BindingList<Customer>();
public int Worth
{
get { return customers.Sum(cust => cust.FullBalance); }
}
public Bank()
{
customers.ListChanged += new ListChangedEventHandler(customers_ListChanged);
}
void customers_ListChanged(object sender, ListChangedEventArgs e)
{
Console.WriteLine("A customer has changed.");
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs("Worth"));
}
public void Add(Customer c) { customers.Add(c); }
}
public class Customer : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private BindingList<Account> accounts = new BindingList<Account>();
public int FullBalance
{
get { return accounts.Sum(acc => acc.Balance); }
}
public Customer()
{
accounts.ListChanged += new ListChangedEventHandler(accounts_ListChanged);
}
void accounts_ListChanged(object sender, ListChangedEventArgs e)
{
Console.WriteLine("An account has changed.");
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs("FullBalance"));
}
public void Add(Account a) { accounts.Add(a); }
}
public class Account : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int balance = 0;
public int Balance
{
get { return balance; }
set
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs("Balance"));
}
}
}
class Program
{
static void Main(string[] args)
{
Account a1 = new Account() { Balance = 5 };
Account a2 = new Account() { Balance = 10 };
Account a3 = new Account() { Balance = 15 };
Customer c1 = new Customer(); c1.Add(a1); c1.Add(a2);
Customer c2 = new Customer(); c2.Add(a3);
Bank b = new Bank(); b.Add(c1); b.Add(c2);
Console.WriteLine();
a1.Balance += 100;
}
}
现在,您可以在事件处理程序或类似内容中编写类似if (e.ListChangedType == ListChangedType.ItemChanged)
的内容。