动态

详情 返回 返回

一步一步學習使用LiveBindings(11) 綁定到自定義外觀的ListBox - 动态 详情

雖然在Firemonkey中,TListView是與LiveBindings綁定最為友善的。但是ListBox在一些短平快的中小型的選項列表中也是非常不錯的選擇。

在本課中,將學習到:

  • 如何自定義ListBox的外觀。
  • 如何使用LiveBindings綁定到具有自定義外觀的ListBox。

請將你在《一步一步學習使用LiveBindings(10)》中的項目複製一份,然後開啓這次列表的實際操作。

在這個練習中,將在TGrid的右側放一個TListBox,以便進行數據的同步演示,真實的場景中,TListBox應該是類似於上一課的TCombobox,是一個可以多選的複選框。最終效果如下圖:

img

如果您是從《一步一步學習使用LiveBindings(8)》一路學過來的話,就會明白為什麼要在那一課詳細的介紹嚮導,因為在那之後的幾課中,都反覆的在使用嚮導先構建綁定的控件,然後再對控件進行微調。

步驟如下:

1. 現在再次右擊主窗口,單擊“LiveBindings Wizard”打開向導。在嚮導中選擇第一項“Link a Control With a Field”,在第二個任務頁選擇“New Control”,選擇TListBox,第三個任務頁選擇“ProtoTypeBindSource1”,也就是Employee列表,第四個任務頁選擇Field為“ContactName”字段。第5個任務頁什麼也不選,單擊Finish完成。

img

然後,一個與Grid保持同步的,非常簡陋的TListBox就出現了。稍稍調整一下佈局,效果如下圖所示:

img

2. 從工具面板拖一個TStyleBook到主窗體,確保主窗體的StyleBook指向了這個TStyleBook控件。雙擊這個控件,將進入到樣式設計窗口。

選中根節點StyleContainer,然後從工具欄拖一個TLayout到設計窗口上,指定高度為64,寬度為300,在屬性窗口設置StyleName為“customitem”。現在有了一個空白的項。

img

3. 從工具面板拖一個TLayout到第2步的TLayout控件內,這個時候應該嚴重依賴於Structure窗口,因為很容易佈局出現混亂,需要重新刷新設計面板,甚至可能需要關閉樣式窗口。

先將這個TLayout指定Align為MostLeft,在這個TLayout內部,再拖一個TCheckBox控件,指定其Align為Center,StyleName為avalilnow。

再拖一個TImage控件在customitem這個TLayout內,指定其Align也為MostLeft,styleName為icon。
佈局如下所示:

img

4. 接下來,在customitem佈局內部加一個TLayout控件,指定其Align為MostRight,在裏邊加一個TSpeedButton,指定其stylename為“info”。

最後,加了4個Align為Top的TText控件,分別命名為“text",“hiredate”,“salary”和“detail”。

特別注意這裏的大小寫,將來在代碼中引用時,要區分大小寫。

img

注意:請將控件的HitTest均設置為False。
這4個TText控件的TextSettings.HorzAlign均設為Leading,表示將從水平開頭位置進行顯示。

由圖中可以看到,這裏還放了3個accessorymore、accessorycheckmark和accessorydetail,其visible都為false。

這些都是複製自標準的ListBoxItemStyle樣式。可以從工具欄拖一個新的TListBox在主界面上,手動增加一個Item,指定StyleLookUp為“listboxitembottomdetail”,然後右擊鼠標,選擇“Edit Custom Style...”,在StyleBook1中就會新加一個ListBoxItem1Style1樣式,複製裏邊的3個accessory。

做完這一切後,將剛剛添加的TListBox刪除。

4. 回到LiveBindings Desinger視圖,由於現在綁定對象越來越多,為了更快的找到需要的對象,這裏選中了ListBoxContactName和PrototypeBindSource1綁定框,右擊鼠標,選擇 Layers > Add to New Layer菜單項,將其添加到一個新的Layer。

img

在右上角的Layer下拉列表框中,會增加一個新的Layer,將它重命名為友好的名稱,以後只要單擊Layer名就可以快速定位到綁定框。

img

  • 確保將Item.text關聯到ContactName。
  • Item.Detail關聯到Title。
  • Item.Bitmap關聯到ContactBitmap。

5. 選中一條鏈接,可以看到選中了屬性編輯器選中了LinkListControlToFieldContactName,然後切換到Events選項卡,為OnFillingListItem添加事件處理代碼。

procedure TfrmMain.LinkListControlToFieldContactNameFillingListItem(
  Sender: TObject; const AEditor: IBindListEditorItem);
var
  Item:TListBoxItem;
begin
  //得到當前的TListBoxItem
  Item:= (AEditor.CurrentObject as TListBoxItem);
  //指定項的高度是樣式設計器的高度
  Item.Height:=68;
  //指定樣式為自定義的樣式名。
  Item.StyleLookup :='customitem';
  //暫時指定Accessory為aMore.
  Item.ItemData.Accessory:=TListBoxItemData.TAccessory.aMore;
end;

按F9鍵運行程序,自定義的ListBox果然顯示了不俗的效果。

img

雖然有一部分文本框已經顯示了數據,但是Salary、HireDate和AvailNow仍然沒有顯示,繼續添加代碼,LinkListControlToFieldContactNameFillingListItem完整的處理代碼如下:

procedure TfrmMain.LinkListControlToFieldContactNameFillingListItem(
  Sender: TObject; const AEditor: IBindListEditorItem);
var
  Item:TListBoxItem;
  emp:TEmployee;
begin
  //得到當前的TListBoxItem
  Item:= (AEditor.CurrentObject as TListBoxItem);
  //指定項的高度是樣式設計器的高度
  Item.Height:=70;
  //指定樣式為自定義的樣式名。
  Item.StyleLookup :='customitem';
  //暫時指定Accessory為aMore.
  Item.ItemData.Accessory:=TListBoxItemData.TAccessory.aMore;
  //得到當前記錄對象
  emp:=bsEmployee.List[bsEmployee.CurrentIndex];
  if emp<>nil then
  begin
    Item.StylesData['availnow'] := emp.AvailNow;
    Item.StylesData['hiredate'] := formatdatetime('MM/DD/YYYY',emp.HireDate);
    Item.StylesData['salary'] := format('%.2m',[Currency(emp.Salary)]);
    //設置按鈕的單擊事件
    Item.StylesData['info.OnClick'] := TValue.From<TNotifyEvent>(DoInfoClick); // set OnClick value
  end;
end;

這裏使用Item.StylesData鍵值對給樣式中的其他對象進行了賦值,最後
注意這個語法TValue.From(DoInfoClick),這是為info.OnClick事件關聯了事件處理代碼。

代碼如下:

//遞歸查找樣式對象的函數
function FindItemParent(Obj: TFmxObject; ParentClass: TClass): TFmxObject;
begin
  Result := nil;
  if Assigned(Obj.Parent) then
    if Obj.Parent.ClassType = ParentClass then
      Result := Obj.Parent
    else
      Result := FindItemParent(Obj.Parent, ParentClass);
end;


procedure TfrmMain.DoInfoClick(Sender: TObject);
var
  Item : TListBoxItem;
begin
  //得到當前樣式對象的頂層TListBoxItem容器對象實例
  Item := TListBoxItem(FindItemParent(Sender as TFmxObject,TListBoxItem));
  //顯示信息
  if Assigned(Item) then
    ShowMessage('你單擊了 ' + IntToStr(Item.Index) + ' 號項目');
end;

FindItemParent這個函數將會查找當前Info樣式對象的父項,遞歸直到找到TListBoxItem對象,獲得當前項的信息,再用ShowMessage顯示信息。

最終效果如下:

img

當單擊“詳細”按鈕時,可以看到果然成功的響應了事件處理代碼。

img

Item.ItemData實際上和Item.StylesData是完成了類似的功能,Item.ItemData會訪問樣式中預定義的功能,比如一個StyleName為“text”的TText控件表示文本,一個StyleName為icon的TImage用來顯示圖像。Accessory則用來顯示右側的按鈕欄。

它們也會出現在可綁定的列表,如果無法直接綁定,只能通過Item.StylesData['salary']這樣的語法進行操作。

總結

TListBox雖然提供了無比強大的自定義功能,但它仍然不是萬能的,它不適合顯示特別複雜的項,適合於簡短的,只讀的或者是外觀不是特別複雜的對象。

TListView是與LiveBindings綁定友好的,更加強大的列表控件,將在下一節介紹。

Add a new 评论

Some HTML is okay.