kbmMW 5.10.20發布了,這個版本解決了我提出的問題,當對DataSet增刪記錄時,ListView能夠同步顯示。下面看看具體的實現代碼。
為了解決上面的問題,作者為IkbmMWBindingNavigator接口增加了下面的方法:
IkbmMWBindingNavigator = interface ...... function Delete:boolean; function Insert:boolean; overload; function Insert(const ANames:array of string; const AValues:array of TValue):boolean; overload; function Append:boolean; overload; function Append(const ANames:array of string; const AValues:array of TValue):boolean; overload; procedure Refresh; property Value[const AName:string]:TValue read GetValue write SetValue; end;
通過上面的方法,即可實現對數據集的增加、刪除等操作。
接下來看一下具體的實現過程:
第一步,綁定DataSet與ListView並取得返回的接口IkbmMWBinding。通過IkbmMWBinding接口的屬性Navigator,可以訪問IkbmMWBindingNavigator接口,從而調用上面新增的方法。
procedure TForm1.Button9Click(Sender: TObject); begin bnd:=nil; Binding.Clear; //ListView1.Items.Clear; dataset:=mt; dataset.disableControls;//kbmMW 5.10.10必須調用,kbmMW 5.10.20可以不調用了,這是改進的地方 bnd:=Binding.Bind(dataset,'f1',Edit1,'Text',[mwboTwoWay]); Binding.Bind(dataset,'f2',Edit2,'Text',[mwboTwoWay]); Binding.Bind(dataset,'f3',DateEdit1,'Date',[mwboTwoWay]); bnd:= Binding.Bind(dataset,'f1',ListView1,'#Text1'); Binding.Bind(dataset,'f2',ListView1,'#Text2'); Binding.Bind(dataset,'f3',ListView1,'#Text3'); Binding.Bind(dataset,'@',ListView1,'@',[mwboTwoWay]); dataset.EnableControls;//kbmMW 5.10.10必須調用,kbmMW 5.10.20可以不調用了,這是改進的地方 end;
當執行這段代碼后,會出現下面的結果:
ListView正確的顯示了數據集的所有記錄內容。無論我們是執行dataset.Next還是bnd.Navigator.Next,ListView與dataSet都會同步顯示當前記錄的位置。
第二步,實現刪除
現在我們刪除一條記錄:
procedure TForm1.Button12Click(Sender: TObject); begin // mt.Delete; // bnd.Navigator.Refresh; bnd.Navigator.Delete; end;
如果直接操作數據集,執行Delete方法,那么,還需要執行bnd.Navigator.Refresh;
如果直接通過bnd執行Delete方法,則不需要執行Refresh方法。
第三步,實現增加
procedure TForm1.Button11Click(Sender: TObject); begin // mt.Append; // mt.FieldByName('f1').Value:='101'; // mt.FieldByName('f2').Value:=101; // mt.Post; // // bnd.Navigator.Refresh; bnd.Navigator.Append; bnd.Navigator.Value['f1']:='101'; bnd.Navigator.Value['f2']:=101; bnd.Navigator.Value['f3']:=Date; end;
上面代碼,象刪除操作一樣,可以通過數據集實現,也可以通過bnd接口實現。當通過數據集實現時,需要調用Refresh方法。
這里有個bug,kbmMW 5.10.10就存在,現在5.10.20還沒有修復,下面是我修改的代碼:
procedure TkbmMWBindingDatasetNavigator.SetValue(const AName:string; const AValue:TValue); var fld:TField; begin if IsValid then begin fld:=FDataset.FindField(AName); if fld<>nil then begin if not (FDataset.State in [dsEdit,dsInsert]) then//+++++ FDataset.Edit; //+++++ fld.AsVariant:=TkbmMWRTTI.ConvertValue2Variant(AValue,nil); end; end; end;
這是個小問題,就是FDataSet沒在編輯狀態。
5.10.10,需要這樣調用:就是退出當前界面時,要清空bnd接口變量,讓Binding能夠正確的釋放,不然,退出應用時會產生AV錯誤。
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin bnd:=nil; Binding.Clear; end;
kbmMW 5.10.20,SmartBinding綁定TDataSet與TListView,對我來說,是一個質的飛躍!可以實用到項目中了。
當然,在具體使用時,還會遇到一些問題,需要自己來處理,比如,用TDateEdit綁定一個TField,當在TDateEdit中輸入日期,會產生錯誤,
原因就是SmartBinding是即時轉換輸入值到對應的TField,而這時候,還沒有完整的輸入一個日期。可以用下面的代碼來處理:
procedure TForm1.DateEdit1Enter(Sender: TObject); begin Binding.EnableByName('DateEdit1',False);//進入這個控件時,暫時屏蔽綁定 end; procedure TForm1.DateEdit1Exit(Sender: TObject); begin Binding.EnableByName('DateEdit1',True);//退出時打開綁定 end;
上面只是我暫時想到的辦法,也不太盡人意,但總算避免了出錯。類似的控件還會有這樣的問題,一時間想不出更好的辦法。
查看kbmMW 5.10.20的更新日志,對SmartBinding框架,為TkbmMWScheduler增加了Start, Stop 及 Shutdown 方法,為TkbmMWBindings增加了Shutdown方法,通過Binding.Shutdown調用,TkbmMWEvents也增加了Shutdown方法,退出應用時作者建議我們調用以保證程序更好的退出。