红鱼儿

统计

SmartBinding实现DataSet与ListView的绑定及同步显示

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错误。

现在,5.10.20没有这个必要了,可以什么都不调用,也不会产生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方法,退出应用时作者建议我们调用以保证程序更好的退出。

 

posted on 2019-11-27 15:02  红鱼儿  阅读(...)  评论(...编辑  收藏