什麼是數據綁定 數據綁定是將一個用戶界面元素的屬性綁定到一個類型/對象實例上的某個屬性的方法,實現該元素屬性和該對象實例屬性在一方數值修改時另一方的數值也隨之修改。 百度百科中的數據綁定的舉例:如果一個開發者有一個Customer類型的實例,那麼他就可以把Customer的“Name”屬性綁定到一個 ...
什麼是數據綁定
數據綁定是將一個用戶界面元素的屬性綁定到一個類型/對象實例上的某個屬性的方法,實現該元素屬性和該對象實例屬性在一方數值修改時另一方的數值也隨之修改。
百度百科中的數據綁定的舉例:如果一個開發者有一個Customer類型的實例,那麼他就可以把Customer的“Name”屬性綁定到一個TextBox的“Text”屬性上。“綁定”了這2個屬性之後,對TextBox的Text屬性的更改將“傳播”到Customer的Name屬性,而對Customer的Name屬性的更改同樣會“傳播”到TextBox的Text屬性。Windows窗體的簡單數據綁定支持綁定到任何public或者internal級別的·NET Framework屬性,同樣可以利用資料庫來簡單地綁定頁面控制項的單個屬性。
在此之前做項目的時候做過C#編寫的WPF應用程式,對其中的數據綁定有一些應用,感覺非常方便,開發效率很高。
C#WPF數據綁定舉例:
先建模型類,告警類:
1 public class CAlarm //告警類 2 { 3 public int iID { get; set; } //告警對象編號 4 public String sTsName { get; set; } //告警對象名稱 5 public String sAlarmLevel { get; set; } //告警級別 6 public String sDesc { get; set; } //告警描述 7 public DateTime dAlarmTime { get; set; } //告警時間 8 }
頁面佈局代碼:
1 <Window x:Class="WPFBinding.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="告警列表" Height="350" Width="487"> 5 <Grid Height="311" Width="464"> 6 <ListView Name="listView1" Height="311" Width="464"> 7 <ListView.View> 8 <GridView> 9 <GridViewColumn Header="編號" DisplayMemberBinding="{Binding iID}" Width="50"></GridViewColumn> 10 <GridViewColumn Header="對象名稱" DisplayMemberBinding="{Binding sTsName}" Width="100"></GridViewColumn> 11 <GridViewColumn Header="告警級別" DisplayMemberBinding="{Binding sAlarmLevel}" Width="60"></GridViewColumn> 12 <GridViewColumn Header="告警描述" DisplayMemberBinding="{Binding sDesc}" Width="100"></GridViewColumn> 13 <GridViewColumn Header="告警時間" DisplayMemberBinding="{Binding dAlarmTime}" Width="100"></GridViewColumn> 14 </GridView> 15 </ListView.View> 16 </ListView> 17 </Grid> 18 </Window>
然後是MainWindow的代碼:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input; 10 using System.Windows.Media; 11 using System.Windows.Media.Imaging; 12 using System.Windows.Navigation; 13 using System.Windows.Shapes; 14 using System.Collections.ObjectModel; 15 16 namespace WPFBinding 17 { 18 /// <summary> 19 /// MainWindow.xaml 的交互邏輯 20 /// </summary> 21 public partial class MainWindow : Window 22 { 23 private IList<CAlarm> m_ilAlarms = new ObservableCollection<CAlarm>(); 24 public MainWindow() 25 { 26 DateTime dt = new DateTime(); 27 TimeSpan ts = new TimeSpan(0, 0, 2, 0, 0); 28 29 m_ilAlarms.Add(new CAlarm() { iID = 1, sTsName = "對象1", sAlarmLevel = "一級告警", sDesc = "水浸檢測到漏水", dAlarmTime = dt }); 30 m_ilAlarms.Add(new CAlarm() { iID = 2, sTsName = "對象1", sAlarmLevel = "二級告警", sDesc = "水浸檢測到漏水", dAlarmTime = dt = dt.Add(ts) }); 31 m_ilAlarms.Add(new CAlarm() { iID = 3, sTsName = "對象2", sAlarmLevel = "一級告警", sDesc = "水浸檢測到漏水", dAlarmTime = dt = dt.Add(ts) }); 32 m_ilAlarms.Add(new CAlarm() { iID = 4, sTsName = "對象3", sAlarmLevel = "三級告警", sDesc = "水浸檢測到漏水", dAlarmTime = dt = dt.Add(ts) }); 33 m_ilAlarms.Add(new CAlarm() { iID = 5, sTsName = "對象2", sAlarmLevel = "一級告警", sDesc = "水浸檢測到漏水", dAlarmTime = dt = dt.Add(ts) }); 34 InitializeComponent(); 35 36 37 this.listView1.ItemsSource = m_ilAlarms; 38 } 39 } 40 41 public class CAlarm //告警類 42 { 43 public int iID { get; set; } //告警對象編號 44 public String sTsName { get; set; } //告警對象名稱 45 public String sAlarmLevel { get; set; } //告警級別 46 public String sDesc { get; set; } //告警描述 47 public DateTime dAlarmTime { get; set; } //告警時間 48 } 49 }
運行結果查看綁定:
MainWindow後端代碼使用ObservableCollection這個集合,可以雙向綁定。
private IList<CAlarm> m_ilAlarms = new ObservableCollection<CAlarm>();是定義一個雙向綁定的集合
以下是界面綁定內容
<GridViewColumn Header="編號" DisplayMemberBinding="{Binding iID}" Width="50"></GridViewColumn>
<GridViewColumn Header="對象名稱" DisplayMemberBinding="{Binding sTsName}" Width="100"></GridViewColumn>
<GridViewColumn Header="告警級別" DisplayMemberBinding="{Binding sAlarmLevel}" Width="60"></GridViewColumn>
<GridViewColumn Header="告警描述" DisplayMemberBinding="{Binding sDesc}" Width="100"></GridViewColumn>
<GridViewColumn Header="告警時間" DisplayMemberBinding="{Binding dAlarmTime}" Width="100"></GridViewColumn>
使用DisplayMemberBinding="{Binding iID}"的方式綁定
當然WPF中還有其他綁定數據到界面元素的方法和綁定類型,在此不再一一贅述。我想說的是WPF的這種綁定的方式大大提高了開發的效率。
然後在最近的一個web應用的項目中前端和後端分離,使用ajax獲取後端json數據,然後拿到數據後再通過js刷新到web頁面的dom對象相應的屬性中顯示在頁面上。
js代碼寫了一大片一大片的。好累人啊。
聯想到WPF的開發高效,現在真的好痛苦啊。
我是一個很懶偷姦耍滑的人。怎麼辦?度娘。果然有現成的:
以下是度娘百科中的內容:
-
AngularJS
編輯
<script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
<p>雙向數據綁定:</p> <input type="text" [(ngModel)]="user.name"/> <div [ngStyle]="style1">{{user.name}}</div>
js代碼:
//ts代碼 user:any = { name:"12345" }
直接搞定。
好高效啊!
我能不能自己寫個綁定代碼?試試:
先做一個文本框和json對象綁定的試試。
查資料發現es5的特性get/set訪問器有希望實現這個雙向綁定的功能
上代碼:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <title>setAndgetTest</title> 6 <style> 7 html, 8 body { 9 width: 100%; 10 height: 100%; 11 overflow: hidden; 12 } 13 </style> 14 <script type="text/javascript"> 15 16 //聲明一個json對象用來和dom對象綁定 17 var theObj = { 18 student_id: 100001, 19 name: "Leao", 20 age: 31, 21 phoneNmb: "18618328433" 22 }; 23 24 var CBinding = function(obj) { 25 var vals = {}; 26 /* 27 private變數,用來保存對象屬性值的集合,只保存基本類型,以json形式保存,比如vals最終可能是這樣: 28 { 29 name:"Leao", 30 student_id: 100001, 31 age: 31, 32 phoneNmb: "18618328433" 33 } 34 */ 35 36 var doms = {}; 37 /* 38 private變數,用來保存dom對象的集合,也就是vals的內容跟dom對象的綁定,doms最終可能是這樣 39 { 40 Obj:domObj, //domObj是name綁定的dom對象 41 protertyName:"value" //protertyName是name在dom對象domObj上綁定的屬性名稱 42 } 43 44 其實可以把上面的vals修改一下: 45 name: "Leao", 46 age: 31, 47 phoneNmb: "18618328433" 48 { 49 name:{ 50 name: "name1", 51 bindingObj:{ 52 Obj:domObj, 53 protertyName:"value" 54 } 55 }, 56 student_id: 100001,//沒有綁定 57 age: 31,//沒有綁定 58 phoneNmb: "18618328433"//沒有綁定 59 } 60 */ 61 62 this.bInit = false;//是否被初始化 63 64 if (null != obj) { 65 var names = Object.getOwnPropertyNames(obj);//獲取obj的所有屬性名 66 var sFieldName = ""; 67 68 if (null != names && 0 < names.length) { 69 var iIndex = 0, iCount = names.length, val = null; 70 71 for (iIndex = 0; iIndex < iCount; iIndex++) { 72 sFieldName = names[iIndex]; 73 val = obj[sFieldName]; 74 vals[sFieldName] = val; 75 doms[sFieldName] = { 76 Obj: {}, //保存dom對象 77 bSet: false, //是否被綁定 78 protertyName: "" //dom對象的屬性名稱 79 }; 80 81 Object.defineProperty(this, sFieldName, { 82 value: val, 83 configurable: true, //能否使用delete、能否需改屬性特性、或能否修改訪問器屬性、,false為不可重新定義,預設值為true 84 enumerable: true, //對象屬性是否可通過for-in迴圈,flase為不可迴圈,預設值為true 85 writable: true, //對象屬性是否可修改,flase為不可修改,預設值為true 86 }); 87 } 88 } 89 } 90 91 this.bInit = true;//被初始化 92 93 /* 94 綁定方法, 95 @domObj,綁定的dom對象 96 */ 97 this._binding = function(domObj) {// 98 if (null != domObj) { 99 var sName = domObj.name || domObj.id;//綁定按照name或id進行匹配 100 101 if (null != sName && 0 < sName.length) { 102 var theVal = vals[sName]; 103 var theDom = doms[sName]; 104 105 if (null != theVal && null != theDom) { //查看是存在sName的的值和綁定對象 106 var fieldName = "value"; //綁定的dom對象屬性名稱,此處只實現了value以後可以在本方法中添加一個參數用來表示屬性名稱 107 108 theDom.Obj = domObj; //保存綁定的dom對象引用/指針 109 theDom.bSet = true; //設置綁定標誌 110 theDom.protertyName = fieldName; 111 theDom.Obj[fieldName] = theVal; //直接賦值 112 113 Object.defineProperty(this, sName, { 114 get: function() { //重寫讀取訪問器 115 116 var theDom = doms[sName]; 117 var reValue = null; 118 119 console.log("get:"); 120 console.log(this); 121 if(theDom.bSet){ 122 reValue = theDom.Obj[fieldName];//直接讀取dom對象的fieldName屬性值 123 } 124 else{ 125 reValue = vals[sName]; //未綁定使用保存值 126 console.log(sName + "屬性未綁定,使用保存值"); 127 } 128 return reValue; 129 }, 130 set: function(val) {//重寫設置訪問器 131 var theDom = doms[sName]; 132 133 vals[sName] = val;//保存值 134 console.log("set:"); 135 console.log(this); 136 if(theDom.bSet){ 137 theDom.Obj[fieldName] = val;//直接設置dom對象的fieldName屬性值 138 } 139 else{ 140 console.log(sName + "屬性未綁定,使用保存值"); 141 } 142 } 143 }); 144 } 145 } 146 } 147 } 148 } 149 150 CBinding.prototype.binding = function(domObj) { //定義綁定原型方法 151 this._binding(domObj);//調用定義的方法 152 }; 153 154 function bindingObj(domObj, dataObj) { //dom對象和json對象綁定,返回新的綁定對象 155 var rObj = null; 156 if (null != domObj && null != dataObj) { 157 if (null == dataObj.bInit) { 158 rObj = new CBinding(dataObj); 159 } else { 160 rObj = dataObj; 161 } 162 rObj.binding(domObj); 163 } 164 165 return rObj; 166 } 167 168