在以前的文章中,我介紹了SmartBinding做爲Delphi的一個新的易於使用和智能的綁定框架。介紹了包括綁定對象,列表,常規數據和可視控件,以及如何使用導航器,全部這些都用代碼作了演示。html
本文將重點關注下一個kbmMW版本中包含的新SmartBinding功能(SmartBinding v2),預計很快就會發布。數據庫
爲使kbmMW SmartBind更加智能,目的之一就是要刪除全部重複的綁定代碼,使開發者只關注具體的功能需求。經過代碼執行SmartBinding很是簡單,但爲了更容易實現,請看下面的演示:
express
先作一個簡單的Form,如上圖,Form包含一個TLabel,一個TButton和兩個TEdit。數組
試着運行它:服務器
當在Edit3輸入內容時,其他控件的Caption和Text都會自動更新。這個功能我已經在以前的SmartBinding博文中介紹過,不知你還記得不?框架
在以前的博文中,有許多Binding.Bind 代碼行將控件綁定在一塊兒,但在此例子中,只須要在TForm的OnCreate事件中用一行綁定代碼:dom
Binding.AutoBind(self);
怎麼可能?!如今的kbmMW SmartBinding可以檢查對象和控件的String屬性,以獲取綁定指令。編碼
Label.Caption屬性中能夠清楚地看到一個綁定指令:{Edit3.Text}spa
只需將綁定內容放在Label.Caption中,Label就會與控件Edit3.Text屬性綁定,來接收數據。按鈕的綁定方式與Edit3相同。第二個TEdit也綁定到Edit3,但在這裏進行了雙向綁定:{Edit3.Text,twoway:true}翻譯
總之,你如今能夠直觀地看到控件從哪裏獲取可視數據。
如今咱們看看Demo應用程序的第二頁:
這顯示瞭如何在一個String屬性中指定多個綁定。TButton控件的Caption屬性如今設置了一個包含2個綁定的數組,一個是Edit1.Text綁定到Label2.Caption,另外一個是Edit1.Text綁定到Label1.Caption。鍵入Edit1將按預期更新兩個Label。
你可能已經注意到,由於咱們使用按鈕的Caption來包含綁定數組,因此按鈕看起來不是最終用戶友好的。可是,這很容易經過如下方法之一來解決:
值語法就象下面這樣定義綁定:
[{value:"Button"},{bind:Edit1.Text, to:Label2.Caption}, { bind: Edit1.Text, to: Label1.Caption}]
運行後的結果:
象值語法這樣的方式,使用常量字符串做爲值,使得Button如今有一個正常的標題了,但也可使用kbmMW配置框架,具體請參閱有關kbmMW配置管理器的博文。
經過將exprToSrc:「expression」和/或exprToDest:「expression」字符串屬性添加到相關綁定部分,也能夠指定目標和源表達式。經過設置disabled:true,能夠將綁定設置爲默認禁用。
若是可以在設置任何真實數據以前設計GUI,那不是很好嗎?換句話說,可以開發實時模型,而且能夠經過開關來轉換爲實際應用程序。
這就是綁定/數據分離發揮做用的地方,如今咱們來看Demo的第三頁:
在這個頁面上,有8個Label,其中7個看起來像是對它們有特定的意義的設置。
經過使用@語法,我告訴kbmMW SmartBinding它應該與名爲test的數據佔位符綁定。
讓咱們運行它:
發生了什麼?在實時系統中,您將看到綁定從@test獲取數據。@Test.Value2和@ test.Value3填充了靜態數據,而其他的綁定產生了看似隨機的數據。這是來自kbmMW的SmartBinding數據生成器的數據示例。
在調用AutoBind以前的某個地方,咱們必須定義可能正在使用的數據佔位符。
var data:IkbmMWBindingData; begin data:=TkbmMWBindingDataGenerator.Create('{'+ ' value1:10,'+ ' value2:"abc",'+ ' value3:88.4,'+ ' value4: &random {'+ ' type:number,'+ ' random:true,'+ ' min:10000,'+ ' max:100000,'+ ' step:5,'+ ' interval:250'+ ' },'+ ' value5: *random,'+ ' value6: *random,'+ ' value7: *random,'+ ' value8: {'+ ' type: values,'+ ' random: true,'+ ' values: ["AAA","BBB","CCC","DDD","EEE"]'+ ' }'+ '}'); Binding.DefineData('test',data); Binding.AutoBind(self); end;
經過調用DefineData,咱們在名稱'test'和將生成並接受綁定數據的東西之間創建了一個連接,在這種狀況下,綁定是TkbmMWBindingDataGenerator的一個實例data。
它接受一個字符串,其中包含簡化的YAML,描述了該生成器應爲其生成數據的各類命名屬性。每一個命名屬性能夠是常量值,如value1,value2和value3,也能夠是描述如何生成特定命名屬性的數據的對象。
看看value4,咱們能夠看到它是一個對象(它以花括號開頭和結尾),而且它包含許多定義數據生成的屬性。
類型目前能夠是如下之一:
若是它的編號可使用這些附加屬性:
若是是其值,則可使用如下附加屬性:
kbmMW支持添加其餘自定義數據生成器類型。
咱們使用命名屬性value4看到的一個特殊語法是YAML錨點(&random)。定義時,其餘命名屬性值可使用* random語法引用相同的定義。這就是爲何value5,6和7都返回隨機值的緣由。
因此如今咱們瞭解如何定義數據生成器。可是如何在開發過程當中使用真實數據替換數據生成器?
很簡單。例如。
type TTest = class private FVal1:kbmMWNullable<integer>; FVal2:kbmMWNullable<string>; FVal3:kbmMWNullable<double>; FVal4:kbmMWNullable<double>; FVal5:kbmMWNullable<double>; FVal6:kbmMWNullable<double>; FVal7:kbmMWNullable<integer>; FVal8:kbmMWNullable<string>; public constructor Create; property Value1:kbmMWNullable<integer> read FVal1 write FVal1; property Value2:kbmMWNullable<string> read FVal2 write FVal2; property Value3:kbmMWNullable<double> read FVal3 write FVal3; property Value4:kbmMWNullable<double> read FVal4 write FVal4; property Value5:kbmMWNullable<double> read FVal5 write FVal5; property Value6:kbmMWNullable<double> read FVal6 write FVal6; property Value7:kbmMWNullable<integer> read FVal7 write FVal7; property Value8:kbmMWNullable<string> read FVal8 write FVal8; end; ... constructor TTest.Create; begin inherited; FVal1:=21; FVal2:='TESTING'; FVal3:=11.1; FVal4:=22.2; FVal5:=33.3; FVal6:=44.4; FVal7:=55; FVal8:='TESTING more!'; end; ... begin testdata:=TTest.Create; Binding.DefineData('test',testdata); end;
調用此代碼時,咱們會動態地使用對象testdata中的數據替換數據生成器。所以,單擊「Redefine test data」按鈕將產生下面的運行結果:
所以,咱們如今已經展現了真正的關注點分離,這使得開發者能夠獨立地設計GUI及控制代碼,而且能夠做爲團隊中我的單獨任務來開發數據層。
如今咱們來到Demo的最後一頁。
這也是一個綁定分離的演示。
在這裏,咱們將對象列表定義爲初始綁定數據:
TLine = class private FVal1:kbmMWNullable<string>; FVal2:kbmMWNullable<integer>; FVal3:kbmMWNullable<double>; public property Val1:kbmMWNullable<string> read FVal1 write FVal1; property Val2:kbmMWNullable<integer> read FVal2 write FVal2; property Val3:kbmMWNullable<double> read FVal3 write FVal3; end; TLines = TObjectList<TLine>; ... FLines:=TLines.Create; ... var line1,line2,line3:TLine; begin Flines:=TLines.Create; line1:=TLine.Create; line2:=TLine.Create; line3:=TLine.Create; line1.Val1:='Hej 1'; line1.Val2:=1; line1.Val3:=1.1; line2.Val1:='Hej 2'; // line2.Val2.IsNull:=true; line2.Val3:=2.2; line3.Val1:='Hej 3'; line3.Val2:=3; line3.Val3:=3.3; Flines.Add(line1); Flines.Add(line2); Flines.Add(line3); Binding.DefineData('test2',FLines); end;
咱們(在這段代碼中爲了它的樂趣)將FLines數據綁定到可視控件:
Binding.Bind(Flines,'Val1',edVal1,'Text',[mwboTwoWay]).Navigator; Binding.Bind(Flines,'Val2',edVal2,'Text',[mwboTwoWay]); Binding.Bind(Flines,'Val3',edVal3,'Text',[mwboTwoWay]);
Next和Prev按鈕包含如下代碼:
// The Prev buttons eventhandler: var nav:IkbmMWBindingNavigator; begin nav:=Binding.GetDataNavigator('test2'); if nav<>nil then nav.Previous; end; // The Next buttons eventhandler: var nav:IkbmMWBindingNavigator; begin nav:=Binding.GetDataNavigator('test2'); if nav<>nil then nav.Next; end;
這段代碼與我在第一篇博文中所展現的略有不一樣,由於我沒有存儲綁定及其導航器以供之後使用,而是根據定義的綁定的名稱在須要時請求導航器。數據。
運行它,它將像咱們習慣的那樣:
咱們可使用Prev和Next按鈕滾動值。
然而…。若是咱們如今想用數據庫中的真實數據替換這個模型列表怎麼辦?
對於演示,咱們使用內存表的內容模擬數據庫中的數據。
mt:=TkbmMemTable.Create(nil); mt.FieldDefs.Add('Val1',ftString,30); mt.FieldDefs.Add('Val2',ftInteger); mt.FieldDefs.Add('Val3',ftFloat); mt.FieldDefs.Add('Val4',ftString,30); mt.CreateTable; mt.Open; mt.AppendRecord(['value 1',1,111.1,'value 1_2']); mt.AppendRecord(['value 2',2,222.2,'value 2_2']); mt.AppendRecord(['value 3',3,333.3,'value 3_2']); mt.AppendRecord(['value 4',4,444.4,'value 4_2']);
如今咱們只須要「切換」數據而不是基於TLines的數據。「從新定義test2數據」的事件處理程序以下所示:
Binding.DefineData('test2',mt);
單擊它,屏幕將當即以下所示:
之前連接到FLines實例的全部綁定如今已從新連接到內存表實例,咱們能夠繼續單擊Prev和Next來滾動數據。
除了上述自動綁定功能,它還支持使用kbmMW中許多其餘地方支持的$(configpath)語法從配置框架中獲取數據,SmartBinding v2還包括:
經過輕鬆支持綁定和數據分離,能夠更輕鬆地完成功能模型(提供服務器和GUI應用程序的數據),只需輕輕一按開關便可將其轉換爲生產代碼。
它能夠以多種方式使用。一種方法是可以經過綁定到來自生成器的簡單靜態文本集,或者經過建立新的自定義翻譯生成器來自動翻譯GUI上的全部文本,您能夠在其中選擇當前語言,所以返回顯示以及如何(控件的大小和位置能夠以相同的方式綁定)。
自動綁定將鍋爐板編碼減小到絕對最小值,同時仍然知足簡單重構GUI的要求,只是由於大多數狀況下的綁定定義將遵循特定控件,只要在其中一個控件中定義綁定便可字符串屬性。在其餘控件(可視或非可見)字符串屬性中定義綁定的狀況下,您至少不會經過簡單地重構控件來鬆散綁定定義。
它能夠輕鬆訪問加載和保存文件的綁定,以處理很是晚的綁定,這能夠在安裝時用於很是動態的應用程序客戶專業化,而不是編譯。