2020-01-09:kbmMW 5.10.20解决了下面的问题,如果你已经升级到该版本,则下面内容没必要读了!
千呼万唤始出来,最新的kbmMW 5.10.01终于发布了,详情可以看xalion发的更新日志。
我期待的Smartbinding for Listview终于来了,在这一版本中,对SmartBinding做了大量的功能扩展与更新,对Listview只是其中之一。这几天一直测试这个Listview的支持情况,发现一个致命的问题,看下面这行代码:
bnd:=Binding.Bind(dataset,'f1',Edit1,'Text',[mwboTwoWay]);
将dataset的f1字段绑定到Edit1的Text属性上,采用双向绑定的方式,目的是通过Edit1,能编辑字段,如同VCL下的DBEdit的一样工作。
但实际的运行情况,与预期不符,当绑定后,SmartBinding将Edit1.Text写到dataset的f1字段中,正好写反了!见下图:
初始情况下,控件Edit1的属性Text值为“Edit1",f1字段值为0,现在”Edit1"正好写入dataset的f1字段中,然后ListView也显示了字段的值为"Edit1"。
向作者反应了这个问题,但作者并没有确认这是一个bug,只好自己动手,通过读SmartBinding的代码,找到一个解决方法,按下面代码修改,所有TkbmMWBinding.Create重载的版本都要改。
constructor TkbmMWBinding.Create(const ABindings:TkbmMWBindings; const ASource:TValue; const ASourceMember:string; const ADestination:TValue; const ADestinationMember:string; const AOptions:TkbmMWBindingOptions = []); var v:TValue; b:boolean; begin inherited Create; .... UpdateInfo; FDestinationProxy.SetValue(FSourceProxy.Value,true); //增加这一行. end;
改后,我们再看看实际运行情况:
上面两个Edit控件及下面的ListView控件终于都显示数据集的内容了!
原理分析:
SmartBinding绑定,就是用TkbmMWBindings来管理TkbmMWBinding对象,即调用TkbmMWBindings.bind增加一个绑定时,会建立一个TkbmMWBinding对象,并将这个对象加到TkbmMWBindings内部的列表中。问题就出在建立TkbmMWBinding对象过程中,没有将数据源的值赋值给目标源,然后,当SmartBind做数据同步时,错误的将目标源的值回写给了数据源,造成逻辑上的错误。我这里的修改,就是增加了这一步:将数据源的值赋值给目标源。
2019-11-26
kbmMW 5.10.10没有按我的意思改,作者认为这不是问题?
2019-11-27
Aone提出这样改,可以避免问题。
procedure TForm1.Button9Click(Sender: TObject); begin bnd:=nil; Binding.Clear; //ListView1.Items.Clear; dataset:=mt; dataset.DisableControls; 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; end;
kbmMW 5.10.10新问题:(5.10.20还存在这个问题)
procedure TForm1.Button11Click(Sender: TObject); begin bnd.Navigator.Append; bnd.Navigator.Value['f1']:='101'; bnd.Navigator.Value['f2']:=101; end;
上面代码产生错误:dataset not in edit mode.
修正代码:
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 [dsInsert,dsEdit]) then//+++ FDataSet.Edit;//+++ fld.AsVariant:=TkbmMWRTTI.ConvertValue2Variant(AValue,nil); end; end; end;
发给作者,等修正!