在winform中如何實現雙向資料繫結?

mingupupup發表於2024-03-18

什麼是雙向資料繫結?

雙向資料繫結是一種允許我們建立持久連線的技術,使模型資料和使用者介面(UI)之間的互動能夠自動同步。這意味著當模型資料發生變化時,UI會自動更新,反之亦然。這種雙向資料繫結極大地簡化了UI和模型資料之間的同步,使開發者可以更專注於業務邏輯,而不是手動處理UI和資料的同步。

今天我想透過winform中DataGridView控制元件為例,介紹在winform中如何實現雙向資料繫結。

一般在winform中使用DataGridView控制元件時,我們可能是這樣使用的:

建立資料來源

以Person類為例:

  public class Person
  {
      public string? Name { get; set; }
      public string? Home { get; set; }
  }

建立Person物件列表:

  // 建立一個Person物件的列表
  List<Person> people = new List<Person>()
  {
      new Person {Name = "張三",Home = "武漢" },
      new Person {Name = "李四",Home = "南昌" },
      new Person {Name = "王五",Home = "福州" },
  };

繫結資料來源:

dataGridView1.DataSource = people;

這個時候的效果如下所示:

image-20240318122622743

當我們進行修改之後,如下所示:

image-20240318122756582

現在列印people列表第一個和第二個person物件的Home屬性值看看:

  Debug.WriteLine(people[0].Home);
  Debug.WriteLine(people[1].Home);

結果如下圖所示:

image-20240318122906132

說明在dataGridView1上修改資料,people列表也被修改了。

現在反過來測試一下,修改people列表第一個和第二個person物件的Home屬性值:

 people[0].Home = "廈門";
 people[1].Home = "廈門";

會發現dataGridView1上的資料不會發生變化,需要我們點選對應的空格之後才會發生改變,如下所示:

顯示值的改變

如果我們這樣寫的話:

 people[0].Home = "廈門";
 people[1].Home = "廈門";
 dataGridView1.UpdateCellValue(1,1);
 dataGridView1.UpdateCellValue(1,2);

效果如下所示:

顯示值的改變2

只改變了一個空格的值,另一個還是需要點選一下,才更新。

在winform中實現雙向資料繫結示例

首先建立一個Student類,如下所示:

 public class Student : INotifyPropertyChanged
 {
    
     private string? _name;

     public string Name
     {
         get { return _name; }
         set
         {
             _name = value;
             // Call OnPropertyChanged whenever the property is updated
             OnPropertyChanged("Name");
         }
     }       
     private string? _home;

     public string Home
     {
         get { return _home; }
         set
         {
             _home = value;
             // Call OnPropertyChanged whenever the property is updated
             OnPropertyChanged("Home");
         }
     }

     // Declare the event
     public event PropertyChangedEventHandler? PropertyChanged;
     // Create the OnPropertyChanged method to raise the event
     protected void OnPropertyChanged(string name)
     {
         var handler = PropertyChanged;
         handler?.Invoke(this, new PropertyChangedEventArgs(name));
     }
 }

實現了INotifyPropertyChanged介面。

建立資料來源:

 // 建立一個Student物件的列表
 BindingList<Student> students = new BindingList<Student>()
 {
         new Student { Name = "張三", Home = "武漢" },
         new Student { Name = "李四", Home = "南昌"  },
         new Student { Name = "王五", Home = "福州"  },
 };

注意這裡使用的是BindingList<T>而不是List<T>

image-20240318125228934

BindingList<T>List<T>的區別

BindingList 和 List 都是用於儲存物件的集合,但它們之間有一些關鍵的區別。

  1. 資料繫結支援:BindingList 是為資料繫結設計的,它實現了 IBindingList 介面。這意味著當 BindingList 中的資料發生更改時(例如,新增、刪除或修改項),它會自動通知繫結到它的任何 UI 控制元件。這對於 Windows Forms 或 WPF 這樣的 UI 框架非常有用,因為它們可以自動更新以反映資料的更改。相比之下,List 不支援資料繫結。
  2. 事件通知:BindingList 提供了一些額外的事件,如 ListChanged,這可以讓你知道列表何時被修改。List 沒有這樣的事件。
  3. 效能:由於 BindingList 提供了額外的功能,所以在某些情況下,它可能比 List 慢一些。如果你不需要資料繫結或更改通知,那麼 List 可能會提供更好的效能。

繫結資料來源:

   dataGridView1.DataSource = students;

更改資料來源的值,檢視UI是否會自動改變:

 students[0].Home = "廈門";
 students[1].Home = "廈門";  

實現的效果如下所示:

值的改變3

發現當資料的值發生改變時,dataGridView1會自動進行更新。

編輯dataGridView1檢視資料來源是否會發生改變,編輯之後如下圖所示:

image-20240318163841499

檢視結果:

 Debug.WriteLine(students[0].Home);
 Debug.WriteLine(students[1].Home);

結果如下圖所示:

image-20240318163929141

說明編輯dataGridView1產生的更改也會導致資料來源的更改。

總結

以上就是在winform中實現雙向資料繫結的一次實踐,要點有兩個,第一個是類實現INotifyPropertyChanged,第二個是用BindingList<T>代替List<T>,希望對你有所幫助。

相關文章