2009-07-13 31 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