|
业务逻辑与界面元素分离的一次小尝试
<div id="cnblogs_post_body">项目中有一个需求,为单据的表头增加自定义项。受制于现在的架构和表头布局自定义的实现机制,自定义项的内容只能预先在IDE里面创建好,而不能通过代码动态创建,只好在单据基类里面预先放入一组控件。由于自定义项本身需要提供编辑、参照、配置、读取与保存等操作,而基类本身已经臃肿不堪,接这个机会尝试一次界面与业务逻辑分离的尝试。因为架构中本身没有数据访问曾的设计和实现,而这个仅仅是作为一个尝试,因此控制类里面并没有对数据访问这块进行分离。类图如下:

因为自定义项目前支持的是3个,所以定义了一个常量来描述自定义项的个数,以后如果有扩充,修改这个常量即可。
详细代码如下:
<div class="cnblogs_code"> 1 { 2 该类用于控制单据表头自定义项。 3 created by fhying@2012.05.04 4 } 5 unit BillTitleCustomItemClass; 6 7 interface 8 9 uses 10 SysUtils, Classes, Controls, Variants, Dialogs, DB, DBClient, cxEdit, cxDBEdit, 11 Forms, Messages; 12 13 const 14 Const_BillTitleCustomItem_MAX = 3; 15 16 type 17 TBillTitleCustomItem = record 18 itemindex : Integer; {自定义项序号(1-3)} 19 itemtype : Integer; {自定义项类型(0编辑、1参照)} 20 itemdatasource : string; {参照的话,数据来源(目前考虑的是基本信息表,如附加说明)} 21 itemdatafield : string; {参照的话,数据来源的字段} 22 end; 23 TBillTitleCustomItems = array[1..Const_BillTitleCustomItem_MAX] of TBillTitleCustomItem; 24 25 TBillTitleCustomItemClass = class(TComponent) 26 private 27 FcdsSQL : TClientDataSet; 28 FBillType: Integer; 29 FBillTitleCustomItems : TBillTitleCustomItems; 30 FBillTitleCustomDataSource: TDataSource; 31 function GetBillTitleCustomItems: TBillTitleCustomItems; 32 procedure SetBillTitleCustomDataSource(const Value: TDataSource); 33 protected 34 { 根据索引获取自定义项的编辑组件 } 35 function GetButtonEdit(AItemIndex : Integer) : TcxDBButtonEdit; virtual; 36 { 初始化自定义项内容 } 37 procedure InitBillTitleCustomItems; 38 { 创建cds,用于执行sql语句 } 39 procedure CreateCDS; 40 { 保存自定义项配置到数据库 } 41 function SaveBillTitleCustomItems(AItemIndex : Integer = 0) : Boolean; 42 { 从数据库读取自定义项配置 } 43 procedure LoadBillTitleCustomItems; 44 { 为自定义项编辑组件进行事件绑定 } 45 procedure BindcxButtonEdits(AItemIndex : Integer = 0); virtual; 46 { 绑定自定义项组件的按钮单击事件 } 47 procedure PropertiesButtonClick(Sender: TObject; AButtonIndex: Integer); 48 { 执行自定义项编辑组件的参照功能 } 49 procedure Reference(AItemIndex : Integer); 50 { 打开自定义项的配置界面 } 51 procedure CustomConfig(AItemIndex : Integer); 52 { 绑定数据源 } 53 procedure SetEditDataSource; 54 public 55 { 自定义构造函数,传入单据类型。 } 56 constructor CreateMy(AOwnerForm : TComponent; ABillType : Integer); virtual; 57 destructor Destroy; override; 58 { 对外部调用者公布自定义项配置内容 } 59 property BillTitleCustomItems : TBillTitleCustomItems read GetBillTitleCustomItems; 60 { 外部调用者给对象设置数据源 } 61 property BillTitleCustomDataSource : TDataSource read FBillTitleCustomDataSource write SetBillTitleCustomDataSource; 62 end; 63 64 implementation 65 66 uses BillTitleCustomItemForm, un_DM, un_ShowForm, Main, PDWizard, 67 BaseBillA, ProdDw, un_ToolsLC; 68 69 { TBillTitleCustomItemClass } 70 71 procedure TBillTitleCustomItemClass.BindcxButtonEdits(AItemIndex : Integer); 72 var 73 i : Integer; 74 procedure BindcxButtonEdit(AItemIndex : Integer); 75 var 76 AItemType : Integer; 77 AEdit : TcxDBButtonEdit; 78 begin 79 AItemType := FBillTitleCustomItems[AItemIndex].itemtype; 80 AEdit := GetButtonEdit(AItemIndex); 81 if AEdit = nil then 82 Exit; 83 case AItemType of 84 0 : { 编辑 } 85 begin 86 AEdit.Properties.Buttons[0].Visible := False; 87 AEdit.Properties.ReadOnly := False; 88 end; 89 1 : { 参照 } 90 begin 91 AEdit.Properties.Buttons[0].Visible := True; 92 AEdit.Properties.ReadOnly := True; 93 end; 94 end; 95 { 用tag来标记是哪个自定义项 } 96 AEdit.Tag := AItemIndex; 97 { 与内置事件绑定 } 98 AEdit.Properties.OnButtonClick := PropertiesButtonClick; 99 end;100 begin101 if AItemIndex = 0 then102 begin103 for i := 1 to Const_BillTitleCustomItem_MAX do104 begin105 BindcxButtonEdit(i);106 end;107 end108 else109 begin110 BindcxButtonEdit(AItemIndex);111 end;112 end;113 114 procedure TBillTitleCustomItemClass.CreateCDS;115 begin116 if FcdsSQL = nil then117 begin118 FcdsSQL := TClientDataSet.Create(nil);119 FcdsSQL.RemoteServer := DM.Con_SubWork;120 FcdsSQL.ProviderName := 'dsp_Oper';121 end;122 end;123 124 constructor TBillTitleCustomItemClass.CreateMy(AOwnerForm: TComponent;125 ABillType: Integer);126 begin127 inherited Create(AOwnerForm);128 FBillType := ABillType;129 InitBillTitleCustomItems;130 LoadBillTitleCustomItems;131 BindcxButtonEdits;132 end;133 134 procedure TBillTitleCustomItemClass.CustomConfig(AItemIndex : Integer);135 var136 frmBillTitleCustomItem: TfrmBillTitleCustomItem;137 begin138 frmBillTitleCustomItem := TfrmBillTitleCustomItem.Create(Application);139 with frmBillTitleCustomItem do140 begin141 try142 ItemType := FBillTitleCustomItems[ItemIndex].itemtype;143 ShowModal;144 if ModalResult = mrOK then145 begin146 FBillTitleCustomItems[AItemIndex].itemtype := ItemType; // 现在只能设置类型。147 if SaveBillTitleCustomItems(AItemIndex) then148 begin149 { 保存前,已经更新了本地变量,所以不需要再从数据库获取一次。及时性要求不需要这样高。 }150 {LoadBillTitleCustomItems;}151 BindcxButtonEdits(AItemIndex);152 end;153 end;154 finally155 Free;156 end;157 end;158 end;159 160 destructor TBillTitleCustomItemClass.Destroy;161 begin162 if FcdsSQL <> nil then163 begin164 FcdsSQL.Close;165 FcdsSQL.Free;166 end;167 inherited;168 end;169 170 function TBillTitleCustomItemClass.GetBillTitleCustomItems: TBillTitleCustomItems;171 begin172 Result := FBillTitleCustomItems;173 end;174 175 function TBillTitleCustomItemClass.GetButtonEdit(176 AItemIndex: Integer): TcxDBButtonEdit;177 var178 AEditName : string;179 AEdit : TComponent;180 begin181 AEditName := 'edtBillTitleCustomItem' + IntToStr(AItemIndex);182 AEdit := TForm(Owner).FindComponent(AEditName);183 if (AEdit <> nil) and (AEdit is TcxDBButtonEdit) then184 Result := TcxDBButtonEdit(AEdit)185 else186 Result := nil;187 end;188 189 procedure TBillTitleCustomItemClass.InitBillTitleCustomItems;190 var191 i : Integer;192 begin193 for i := 1 to Const_BillTitleCustomItem_MAX do194 begin195 FBillTitleCustomItems.itemindex := i;196 FBillTitleCustomItems.itemtype := 0;197 FBillTitleCustomItems.itemdatasource := 'commoninfo';198 FBillTitleCustomItems.itemdatafield := 'u_Remark';199 end;200 end;201 202 procedure TBillTitleCustomItemClass.LoadBillTitleCustomItems;203 begin204 CreateCDS;205 FcdsSQL.CommandText :=206 'select * from BillTitleCustomItem where billtype = '+IntToStr(FBillType)+' order by ItemIndex';207 FcdsSQL.Open;208 with FcdsSQL do209 begin210 if RecordCount > Const_BillTitleCustomItem_MAX then211 begin212 Exit;213 end;214 First;215 while not Eof do216 begin217 FBillTitleCustomItems[RecNo].itemindex := FieldByName('ItemIndex').AsInteger;218 FBillTitleCustomItems[RecNo].itemtype := FieldByName('itemtype').AsInteger;219 FBillTitleCustomItems[RecNo].itemdatasource := FieldByName('itemdatasource').AsString;220 FBillTitleCustomItems[RecNo].itemdatafield := FieldByName('itemdatafield').AsString;221 222 Next;223 end;224 end;225 end;226 227 procedure TBillTitleCustomItemClass.PropertiesButtonClick(Sender: TObject;228 AButtonIndex: Integer);229 begin230 case AButtonIndex of231 0 : Reference(TcxDBButtonEdit(Sender).Tag);232 1 : CustomConfig(TcxDBButtonEdit(Sender).Tag);233 end;234 end;235 236 { 因为现在这里只是针对进货单和销售单,且参照仅针对附加说明,所以先这样处理。 }237 procedure TBillTitleCustomItemClass.Reference(AItemIndex : Integer);238 var239 szFieldName : string;240 begin241 if tclientdataset(BillTitleCustomDataSource.DataSet).ReadOnly then242 Exit;243 244 fm_main.vpSingleType := 13;245 246 fm_ProdDw := Tfm_ProdDw.create(application);247 try248 with fm_ProdDw do249 begin250 fm_ProdDw.vpCalltype := 3;251 252 T1_Showmodal(fm_ProdDw);253 if modalresult = mrok then254 begin255 szFieldName := 'Item' + IntToStr(AItemIndex);256 tclientdataset(BillTitleCustomDataSource.DataSet).Edit;257 tclientdataset(BillTitleCustomDataSource.DataSet).FieldByName(szFieldName).AsString := cds_SingleList.FieldByName('U_Remark').AsString;258 tclientdataset(BillTitleCustomDataSource.DataSet).Post;259 end;260 end;261 finally262 gl_Trans.Info1 := '';263 fm_ProdDw.free;264 end;265 end;266 267 function TBillTitleCustomItemClass.SaveBillTitleCustomItems(AItemIndex : Integer): Boolean;268 var269 szSQL : string;270 function MakeSaveSQL : string;271 var272 i : Integer;273 szDelete : string;274 szTmp : string;275 begin276 Result := '';277 if AItemIndex = 0 then278 begin279 szDelete := ' delete from BillTitleCustomItem where BillType = '+IntToStr(FBillType);280 281 for i := 1 to Const_BillTitleCustomItem_MAX do282 begin283 szTmp := ' insert into BillTitleCustomItem (BillType, itemindex, itemtype, itemdatasource, itemdatafield) values (%d,%d,%d,'+Char(39)+'%s'+Char(39)+','+Char(39)+'%s'+Char(39)+')';284 with FBillTitleCustomItems do285 szTmp := Format(szTmp, [FBillType, itemindex, itemtype, itemdatasource, itemdatafield]);286 287 Result := Result + szTmp ;//+ Char(13)+Char(10);288 end;289 end290 else291 begin292 szDelete := ' delete from BillTitleCustomItem where BillType = '+IntToStr(FBillType) + ' and itemindex =' + IntToStr(AItemIndex);293 szTmp := ' insert into BillTitleCustomItem (BillType, itemindex, itemtype, itemdatasource, itemdatafield) values (%d,%d,%d,'+Char(39)+'%s'+Char(39)+','+Char(39)+'%s'+Char(39)+')';294 with FBillTitleCustomItems[AItemIndex] do295 szTmp := Format(szTmp, [FBillType, AItemIndex, itemtype, itemdatasource, itemdatafield]);296 Result := Result + szTmp ;297 end;298 299 Result := szDelete + Result;300 end;301 begin302 szSQL := MakeSaveSQL;303 FcdsSQL.CommandText := szSQL;304 try305 FcdsSQL.Execute;306 307 Result := True;308 except309 on e : Exception do310 begin311 Result := False;312 ShowDlg(1, '保存单据表头自定义项设置失败。'+#13+'错误信息:'+#13+e.Message);313 end;314 end;315 end; 316 317 procedure TBillTitleCustomItemClass.SetBillTitleCustomDataSource(318 const Value: TDataSource);319 begin320 FBillTitleCustomDataSource := Value;321 SetEditDataSource;322 end;323 324 procedure TBillTitleCustomItemClass.SetEditDataSource;325 var326 i : Integer;327 AEdit : TcxDBButtonEdit;328 begin329 for i := 1 to Const_BillTitleCustomItem_MAX do330 begin331 AEdit := GetButtonEdit(i);332 AEdit.DataBinding.DataSource := BillTitleCustomDataSource;333 AEdit.DataBinding.DataField := 'Item'+IntToStr(i);334 end;335 end;336 337 end. |
|