2009-07-13 57 views
2

我遇到了一个我知道的情况一定很常见的问题,所以我希望解决方案很简单。我有一个对象,其中包含一个对象列表<>。它还有一些属性反映了列表<>中的对象的集合数据(实际上是绑定列表<>因此我可以绑定到它)。在我的表单中,我有一个DataGridView用于List,还有一些其他字段用于聚合数据。我无法弄清楚如何在DataGridView中的值发生更改时触发刷新聚合数据。Winforms包含列表的数据绑定对象<T>

我试着在列表中的对象的属性发生更改时引发PropertyChanged事件,但似乎没有刷新聚合数据的显示。如果我访问一个聚合属性(例如,将其显示在消息框中),则会刷新主窗体上的文本框。

下面是一些简单的代码来说明我想要做的事:

namespace WindowsFormsApplication1 { 
public class Person { 

    public int Age { 
     get; 
     set; 
    } 

    public String Name { 
     get; 
     set; 
    } 
} 

public class Roster : INotifyPropertyChanged { 

    public BindingList<Person> People { 
     get; 
     set; 
    } 

    public Roster() { 
     People = new BindingList<Person>(); 
    } 

    private int totalage; 
    public int TotalAge { 
     get { 
      calcAges(); 
      return totalage; 
     } 
     set { 
      totalage = value; 
      NotifyPropertyChanged("TotalAge"); 
     } 
    } 

    private void calcAges() { 
     int total = 0; 
     foreach (Person p in People) { 
      total += p.Age; 
     } 
     TotalAge = total; 
    } 

    #region INotifyPropertyChanged Members 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged (String info) { 
     if (PropertyChanged != null) { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
    #endregion 
} 
} 
+0

这看起来与http://stackoverflow.com/questions/601320/winforms-data-binding-bind-to-objects-in-a-list非常相似,可能是它的重复。 – 2009-07-13 15:09:42

回答

3

calcAges方法和TotalAge属性看起来非常可疑。

首先,TotalAge应该是只读的。如果你允许它是公开的和可写的,那么改变组成这个时代的组件的逻辑是什么?

其次,每次获得该值时,您都会触发PropertyChanged事件,这并不好。

Roster类应该是这样的:

public class Roster : INotifyPropertyChanged { 

    public Roster() 
    { 
     // Set the binding list, this triggers the appropriate 
     // event binding which would be gotten if the BindingList 
     // was set on assignment. 
     People = new BindingList<Person>(); 
    } 

    // The list of people. 
    BindingList<Person> people = null; 

    public BindingList<Person> People 
    { 
     get 
     { 
      return people; 
     } 
     set 
     { 
      // If there is a list, then remove the delegate. 
      if (people != null) 
      { 
       // Remove the delegate. 
       people.ListChanged -= OnListChanged; 
      } 

      /* Perform error check here */ 
      people = value; 

      // Bind to the ListChangedEvent. 
      // Use lambda syntax if LINQ is available. 
      people.ListChanged += OnListChanged; 

      // Technically, the People property changed, so that 
      // property changed event should be fired. 
      NotifyPropertyChanged("People"); 

      // Calculate the total age now, since the 
      // whole list was reassigned. 
      CalculateTotalAge(); 
     } 
    } 

    private void OnListChanged(object sender, ListChangedEventArgs e) 
    { 
     // Just calculate the total age. 
     CalculateTotalAge(); 
    } 

    private void CalculateTotalAge() 
    { 
     // Store the old total age. 
     int oldTotalAge = totalage; 

     // If you can use LINQ, change this to: 
     // totalage = people.Sum(p => p.Age); 

     // Set the total age to 0. 
     totalage = 0; 

     // Sum. 
     foreach (Person p in People) { 
      totalage += p.Age; 
     } 

     // If the total age has changed, then fire the event. 
     if (totalage != oldTotalAge) 
     { 
      // Fire the property notify changed event. 
      NotifyPropertyChanged("TotalAge"); 
     } 
    } 

    private int totalage = 0; 

    public int TotalAge 
    { 
     get 
     { 
      return totalage; 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged (String info) { 
     if (PropertyChanged != null) { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 

现在,当列表中的项目性质发生改变,父对象将触发属性更改事件,和任何绑定到它应该随之改变。

-1

我相信你可能会寻找这样的事情

ITypedList

而且ITypedList引线的Google Search你到几个漂亮的博客如何实施。

当我使用ORM时,我通常必须为这些好的数据网格绑定和表示做些操作。

+0

@joshlrogers:对不起,这不是一个绑定数据类型的问题,而是绑定和通知没有正确发生。 ITypedList不会将任何内容添加到尚未由INotifyPropertyChanged公开的通知体验中。 – casperOne 2009-07-13 15:41:37

+0

嗯.....我已经重读了这个问题和你的答案,我想我只是错过了一些东西,也许在早上太早。我假设他正在修改其中一个聚合对象中某个对象的属性。换句话说,他正在修改BindingList中Person的属性,所以他确实没有修改集合本身,而仅仅是集合的一个对象。因此,如果他修改了如何使用ITypedList绑定网格,他可以专门捕获这些基础属性的更改并进行通知。也许我只是没有思考或者过度复杂化问题。 – joshlrogers 2009-07-13 15:51:43