10.16.OrangeUI控件使用说明(列表框控件ListBox)(示例16 使用列表项设计面板 动态绑定多个图片)

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

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

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

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

先讲解一下ListBox和ItemDesignerPanel之前的联系,

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

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

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

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

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

 

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

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

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

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

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

 

 

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

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

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

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

ListBox的ItemHeight设置为100,

 

再在ListBox上放一个ItemDesignerPanel,

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

Image命名为imgPic1和imgPic2,用于显示两张商品图片,

设置Image.SelfOwnMaterial.DrawPictureParam.IsAutoFit为True,

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

 

Label命名为lblCaption1和lblCaption2,用于显示两个商品名称,

设置Label.SelfOwnMaterial.DrawCaptionParam.FontHorzAlign为Center,

再给两个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上的Image和Label不知道显示什么内容,

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

 

重要的事件再声明一遍:

先讲解一下ListBox和ItemDesignerPanel之前的联系,

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;

 

 

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

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

 

 

 

 

 

 

发表评论