WinForm中實(shí)現(xiàn)雙向數(shù)據(jù)綁定的示例詳解
前言
在開(kāi)發(fā) WinForm 應(yīng)用程序時(shí),常常需要將數(shù)據(jù)模型與用戶(hù)界面進(jìn)行同步。傳統(tǒng)的做法是手動(dòng)監(jiān)聽(tīng) UI 變化并更新數(shù)據(jù)模型,或者反過(guò)來(lái)更新 UI 控件,這種方式不僅繁瑣,而且容易出錯(cuò)。
為了解決這個(gè)問(wèn)題,許多現(xiàn)代 UI 框架都支持雙向數(shù)據(jù)綁定(Two-Way Data Binding),即當(dāng)模型數(shù)據(jù)發(fā)生變化時(shí),UI 自動(dòng)更新;而當(dāng)用戶(hù)通過(guò) UI 修改數(shù)據(jù)時(shí),模型也會(huì)自動(dòng)同步變化。這種機(jī)制極大提升了開(kāi)發(fā)效率和代碼可維護(hù)性。
本文將以 WinForms 中的 DataGridView 控件為例,演示不使用雙向綁定時(shí)的數(shù)據(jù)同步問(wèn)題,并詳細(xì)介紹如何通過(guò)實(shí)現(xiàn) INotifyPropertyChanged 接口和使用 BindingList<T> 來(lái)實(shí)現(xiàn)真正的雙向數(shù)據(jù)綁定。
什么是雙向數(shù)據(jù)綁定?
雙向數(shù)據(jù)綁定是一種允許我們創(chuàng)建持久連接的技術(shù),使模型數(shù)據(jù)和用戶(hù)界面(UI)之間的交互能夠自動(dòng)同步。這意味著:
當(dāng)模型數(shù)據(jù)發(fā)生變化時(shí),UI 會(huì)自動(dòng)更新;
當(dāng)用戶(hù)在 UI 上修改數(shù)據(jù)后,模型數(shù)據(jù)也會(huì)自動(dòng)更新。
這種雙向數(shù)據(jù)綁定極大地簡(jiǎn)化了 UI 和模型數(shù)據(jù)之間的同步,開(kāi)發(fā)可以更專(zhuān)注于業(yè)務(wù)邏輯,而不是手動(dòng)處理 UI 和數(shù)據(jù)的同步。
不使用雙向綁定的示例
通常在 WinForms 中使用 DataGridView 控件展示數(shù)據(jù)時(shí),我們會(huì)創(chuàng)建一個(gè)類(lèi)作為數(shù)據(jù)模型,并將其對(duì)象列表綁定到 DataGridView 的 DataSource 屬性中。
例如,我們定義一個(gè) Person 類(lèi):
public class Person
{
public string? Name { get; set; }
public string? Home { get; set; }
}
然后創(chuàng)建一個(gè) List<Person> 數(shù)據(jù)源并綁定:
// 創(chuàng)建一個(gè)Person對(duì)象的列表
List<Person> people = new List<Person>()
{
new Person {Name = "張三", Home = "武漢" },
new Person {Name = "李四", Home = "南昌" },
new Person {Name = "王五", Home = "福州" },
};
dataGridView1.DataSource = people;
綁定后的效果如下圖所示:

當(dāng)我們對(duì) dataGridView1 中的數(shù)據(jù)進(jìn)行修改后,查看 people 列表中的數(shù)據(jù)是否也被更新:
Debug.WriteLine(people[0].Home); Debug.WriteLine(people[1].Home);
結(jié)果如下圖所示:

說(shuō)明在 dataGridView1 上修改數(shù)據(jù)后,people 列表也確實(shí)發(fā)生了變化。
但如果我們反向操作,在代碼中直接修改 people 列表的數(shù)據(jù):
people[0].Home = "廈門(mén)"; people[1].Home = "廈門(mén)";
此時(shí)發(fā)現(xiàn) dataGridView1 上的數(shù)據(jù)并不會(huì)立即刷新,必須點(diǎn)擊某個(gè)單元格才能觸發(fā)更新。

如果我們調(diào)用以下方法強(qiáng)制刷新:
dataGridView1.UpdateCellValue(1, 1); dataGridView1.UpdateCellValue(1, 2);
則可以看到部分?jǐn)?shù)據(jù)更新成功,但仍需手動(dòng)干預(yù):

這表明:默認(rèn)情況下,List<T> 并不能自動(dòng)通知 UI 進(jìn)行更新,因此無(wú)法實(shí)現(xiàn)真正的“雙向綁定”。
在 WinForms 中實(shí)現(xiàn)雙向數(shù)據(jù)綁定示例
為了實(shí)現(xiàn)雙向綁定,我們需要做兩件事:
1、模型類(lèi)實(shí)現(xiàn) INotifyPropertyChanged 接口;
2、使用 BindingList<T> 替代 List<T> 作為數(shù)據(jù)源。
定義 Student 類(lèi)并實(shí)現(xiàn) INotifyPropertyChanged
public class Student : INotifyPropertyChanged
{
private string? _name;
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
private string? _home;
public string Home
{
get => _home;
set
{
_home = value;
OnPropertyChanged(nameof(Home));
}
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
創(chuàng)建 BindingList< Student> 數(shù)據(jù)源
BindingList<Student> students = new BindingList<Student>()
{
new Student { Name = "張三", Home = "武漢" },
new Student { Name = "李四", Home = "南昌" },
new Student { Name = "王五", Home = "福州" }
};
dataGridView1.DataSource = students;
注意這里使用的不再是 List<T >,而是 BindingList<T >。這是關(guān)鍵所在,因?yàn)?nbsp;BindingList<T > 支持?jǐn)?shù)據(jù)變更的通知。
測(cè)試雙向綁定效果
我們?cè)诖a中修改數(shù)據(jù)源:
students[0].Home = "廈門(mén)"; students[1].Home = "廈門(mén)";
此時(shí) dataGridView1 會(huì)自動(dòng)更新,無(wú)需任何額外操作:

同樣地,如果我們?cè)?nbsp;dataGridView1 中編輯數(shù)據(jù),students 數(shù)據(jù)源也會(huì)隨之改變:
Debug.WriteLine(students[0].Home); Debug.WriteLine(students[1].Home);
輸出結(jié)果如下:

這表明雙向綁定已經(jīng)生效。
BindingList< T> 與 List< T> 的區(qū)別
| 特性 | BindingList< T> | List< T> |
|---|---|---|
| 數(shù)據(jù)綁定支持 | ? 支持,自動(dòng)通知控件更新 | ? 不支持 |
| 更改通知事件 | ? 提供 ListChanged 事件 | ? 不提供 |
| 性能 | 相對(duì)稍慢 | 更快 |
| 適用場(chǎng)景 | 需要數(shù)據(jù)綁定的 UI 應(yīng)用 | 僅用于存儲(chǔ)數(shù)據(jù) |
總結(jié)
本文通過(guò)一個(gè)完整的案例,詳細(xì)講解了在 WinForms 中如何實(shí)現(xiàn)真正的雙向數(shù)據(jù)綁定。核心要點(diǎn)如下:
雙向數(shù)據(jù)綁定的本質(zhì) 是讓模型數(shù)據(jù)和 UI 界面保持自動(dòng)同步;
默認(rèn)情況下,List< T> + DataGridView 只能實(shí)現(xiàn)單向綁定(UI -> 數(shù)據(jù)),不能自動(dòng)響應(yīng)數(shù)據(jù)變化;
實(shí)現(xiàn)雙向綁定的關(guān)鍵:
模型類(lèi)必須實(shí)現(xiàn)
INotifyPropertyChanged接口;數(shù)據(jù)源應(yīng)使用
BindingList<T>而不是List<T>。
通過(guò)上述方式,我們可以輕松實(shí)現(xiàn) WinForm 中的數(shù)據(jù)綁定功能,提高開(kāi)發(fā)效率,減少手動(dòng)同步帶來(lái)的錯(cuò)誤和復(fù)雜度。
希望這篇文章對(duì)大家理解 WinForm 中的雙向數(shù)據(jù)綁定有所幫助!大家如果正在開(kāi)發(fā) WinForm 應(yīng)用,不妨嘗試使用這些技術(shù)來(lái)提升的項(xiàng)目質(zhì)量。
最后
以上就是WinForm中實(shí)現(xiàn)雙向數(shù)據(jù)綁定的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于WinForm雙向數(shù)據(jù)綁定的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#使用FileSystemWatcher控件實(shí)現(xiàn)的文件監(jiān)控功能示例
這篇文章主要介紹了C#使用FileSystemWatcher控件實(shí)現(xiàn)的文件監(jiān)控功能,結(jié)合實(shí)例形式分析了C# FileSystemWatcher組件的功能及監(jiān)控文件更改情況的具體使用技巧,需要的朋友可以參考下2017-08-08
C#自定義鼠標(biāo)拖拽Drag&Drop效果之基本原理及基本實(shí)現(xiàn)代碼
拖拽效果無(wú)論是在系統(tǒng)上、應(yīng)用上、還是在網(wǎng)頁(yè)上,拖拽隨處可見(jiàn),下面通過(guò)本文介紹下C#自定義鼠標(biāo)拖拽Drag&Drop效果之基本原理及基本實(shí)現(xiàn)代碼,需要的朋友可以參考下2022-04-04
C#使用foreach語(yǔ)句遍歷隊(duì)列(Queue)的方法
這篇文章主要介紹了C#使用foreach語(yǔ)句遍歷隊(duì)列(Queue)的方法,涉及foreach語(yǔ)句的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04
C#使用反射(Reflect)獲取dll文件中的類(lèi)型并調(diào)用方法
這篇文章主要為大家詳細(xì)介紹了C#使用反射(Reflect)獲取dll文件中的類(lèi)型并調(diào)用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10
C#實(shí)現(xiàn)毫秒轉(zhuǎn)換成時(shí)分秒的方法
這篇文章主要介紹了C#實(shí)現(xiàn)毫秒轉(zhuǎn)換成時(shí)分秒的方法,涉及C#時(shí)間的操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03

