默认ListBoxItem只包含一个图片,也就是它的Icon属性,

列表项设计面板ItemDesignerPanel上也只有一个ItemIconBindingControl来绑定Image,

如果遇到一个列表项上需要显示多个图片,

就需要用到ListBox的动态绑定功能了,

先讲解一下ListBoxItemDesignerPanel之前的联系,

OrangeUI中的ListBox是利用ItemDesignerPanel上面的所有控件来绘制的,

虽然在ListBox中可以显示多个列表项,

但是每个列表项是不会创建属于自己的ItemDesignerPanel的,

那样做不仅会消耗大量的内存,也会使程序卡成一逼。

因此ListBox使用公共的ItemDesignerPanel来绘制每个列表项。

 

再来讲解一下OnPrepareDrawItem这个事件,

ListBox绘制一个列表项之前,先会调用OnPrepareDrawItem

把这个列表项传给OnPrepareDrawItem事件,

用户可以在OnPrepareDrawItem事件中根据传入的列表项进行完全自定义的处理,

处理完之后,再使用ItemDesignerPanel来绘制这个列表项,

 

 

我先讲解一下常用的一种解决方式,

先创建一个窗体,上面个一个ListBox,

双击ListBox,预先创建好两个空白的列表项用于预览效果,

并且不需要给列表项设置任何属性,

ListBoxItemHeight设置为100,

 

再在ListBox上放一个ItemDesignerPanel,

然后ItemDesignerPanel上放两个Image和两个Label,

Image命名为imgPic1imgPic2,用于显示两张商品图片,

设置Image.SelfOwnMaterial.DrawPictureParam.IsAutoFitTrue,

并且先给两个Image设置好图片便于预览效果,

 

Label命名为lblCaption1lblCaption2,用于显示两个商品名称,

设置Label.SelfOwnMaterial.DrawCaptionParam.FontHorzAlignCenter,

再给两个Label设置好标题便于预览效果,

 

不需要给ItemDesignerPanel绑定任何控件,

效果如下:

 

 

定义一个商品对的类,类成员有两个商品名称,两张商品图片,代码如下:

type

  //商品对

  TGoodsPair=class(TObject)

  public

    //商品1名称

    Caption1:String;

    //商品2名称

    Caption2:String;

    //商品1图片

    Pic1:TDrawPicture;

    //商品2图片

    Pic2:TDrawPicture;

  public

    constructor Create;

    destructor Destroy;override;

  end;

{ TGoodsPair }

 

constructor TGoodsPair.Create;

begin

  Pic1:=TDrawPicture.Create;

  Pic2:=TDrawPicture.Create;

end;

 

destructor TGoodsPair.Destroy;

begin

  FreeAndNil(Pic1);

  FreeAndNil(Pic2);

  inherited;

end;

 

 

接下来,我们放个“点击加载”按钮,用于点击的时候加载列表项:

代码如下:

procedure TFrameListBox_BindingMultiPic.btnLoadClick(Sender: TObject);

var

  I: Integer;

  APicServerUrl:String;

  AGoodsPair:TGoodsPair;

  AListBoxItem:TSkinListBoxItem;

begin

  //加载

  Self.lbMultiPic.Prop.Items.BeginUpdate;

  try

    //释放之前的DataObject

    for I := 0 to Self.lbMultiPic.Prop.Items.Count-1 do

    begin

      Self.lbMultiPic.Prop.Items[I].DataObject.Free;

    end;

    //清空列表项

    Self.lbMultiPic.Prop.Items.Clear(True);

 

    //图片服务器链接地址

    APicServerUrl:='http://www.orangeui.cn/download/testdownloadpicturemanager/mobileposthumbpic/';

 

 

    //添加列表项

    AGoodsPair:=TGoodsPair.Create;

    AGoodsPair.Caption1:='阿尔代雪赤霞珠银标';

    AGoodsPair.Pic1.Url:=APicServerUrl+'阿尔代雪赤霞珠银标.jpg';

    AGoodsPair.Caption2:='阿尔岱雪丹娜斯';

    AGoodsPair.Pic2.Url:=APicServerUrl+'阿尔岱雪丹娜斯.jpg';

    AListBoxItem:=Self.lbMultiPic.Prop.Items.Add;

    AListBoxItem.DataObject:=AGoodsPair;

 

 

    //添加列表项

    AGoodsPair:=TGoodsPair.Create;

    AGoodsPair.Caption1:='安溪铁观音';

    AGoodsPair.Pic1.Url:=APicServerUrl+'安溪铁观音.jpg';

    AGoodsPair.Caption2:='西湖龙井';

    AGoodsPair.Pic2.Url:=APicServerUrl+'西湖龙井.jpg';

    AListBoxItem:=Self.lbMultiPic.Prop.Items.Add;

    AListBoxItem.DataObject:=AGoodsPair;

 

    //添加列表项

    AGoodsPair:=TGoodsPair.Create;

    AGoodsPair.Caption1:='安溪铁观音';

    AGoodsPair.Pic1.Url:=APicServerUrl+'安溪铁观音.jpg';

    AGoodsPair.Caption2:='西湖龙井';

    AGoodsPair.Pic2.Url:=APicServerUrl+'西湖龙井.jpg';

    AListBoxItem:=Self.lbMultiPic.Prop.Items.Add;

    AListBoxItem.DataObject:=AGoodsPair;

 

    //添加列表项

    AGoodsPair:=TGoodsPair.Create;

    AGoodsPair.Caption1:='人鱼恋带鱼系列';

    AGoodsPair.Pic1.Url:=APicServerUrl+'人鱼恋带鱼系列.jpg';

    AGoodsPair.Caption2:='食品套餐128';

    AGoodsPair.Pic2.Url:=APicServerUrl+'食品套餐128.jpg';

    AListBoxItem:=Self.lbMultiPic.Prop.Items.Add;

    AListBoxItem.DataObject:=AGoodsPair;

 

 

  finally

    Self.lbMultiPic.Prop.Items.EndUpdate();

  end;

 

end;

 

 

上面代码的主要思路就是创建一个GoodsPair的对象,

给对象设置好商品名称和商品图片链接,

然后把对象放在列表项的DataObject中。

 

 

 

接下来我们运行看一下示例,点击加载按钮:

如上图所示,虽然列表项加载出来了,

但是列表项中的图片和标题没有显示对应的内容,

那是因为我们没有进行绑定,

所以ItemDesignerPanel上的ImageLabel不知道显示什么内容,

动态绑定是在ListBox.OnPrepareDrawItem事件中处理,

 

重要的事件再声明一遍:

先讲解一下ListBoxItemDesignerPanel之前的联系,

OrangeUI中的ListBox是利用ItemDesignerPanel上面的所有控件来绘制的,

虽然在ListBox中可以显示多个列表项,

但是每个列表项是不会创建属于自己的ItemDesignerPanel的,

那样做不仅会消耗大量的内存,也会使程序卡成一逼。

因此ListBox使用公共的ItemDesignerPanel来绘制每个列表项。

 

再来讲解一下OnPrepareDrawItem这个事件,

ListBox绘制一个列表项之前,先会调用OnPrepareDrawItem

把这个列表项传给OnPrepareDrawItem事件,

用户可以在OnPrepareDrawItem事件中根据传入的列表项进行完全自定义的处理,

处理完之后,再使用ItemDesignerPanel来绘制这个列表项,

 

好了,接下来我们完成动态绑定:

双击ListBox.OnPrepareDrawItem事件,

参数Item:TSkinItem就是绘时前所传入的列表项,

需要在单元中引用如下几个单元:

  uDrawCanvas,

  uSkinItems,

  uDrawPicture,

  uSkinListBoxType,

 

再写上如下代码:

procedure TFrameListBox_BindingMultiPic.lbMultiPicPrepareDrawItem(

  Sender: TObject; Canvas: TDrawCanvas;

  ItemDesignerPanel: TSkinFMXItemDesignerPanel; Item: TSkinItem;

  ItemRect: TRect);

var

  AGoodsPair:TGoodsPair;

begin

  //取出设置在Item.DataObject中的GoodsPair对象

  AGoodsPair:=TGoodsPair(Item.DataObject);

 

  //GoodsPair对象中的数据赋给ItemDesignerPanel上面的控件

  Self.lblCaption1.Caption:=AGoodsPair.Caption1;

  Self.imgPic1.Prop.Picture.RefDrawPicture:=AGoodsPair.Pic1;

  Self.imgPic1.Prop.Picture.PictureDrawType:=TPictureDrawType.pdtRefDrawPicture;

 

  Self.lblCaption2.Caption:=AGoodsPair.Caption2;

  Self.imgPic2.Prop.Picture.RefDrawPicture:=AGoodsPair.Pic2;

  Self.imgPic2.Prop.Picture.PictureDrawType:=TPictureDrawType.pdtRefDrawPicture;

 

end;

 

 

接下来再运行看一下示例:

看,每个列表项都显示对应的商品内容了