原文 http://www.malcolmgroves.com/blog/?p=1084

一、新建VCL工程加入TAdapterBingSource控件

二、定一个TPerson类

MyPerson : TPerson;
 TPerson = class
private
FAge: Integer;
FLastname: string;
FFirstname: string;
public
constructor Create(const Firstname, Lastname : string; Age : Integer); virtual;
property Firstname : string read FFirstname write FFirstname;
property Lastname : string read FLastname write FLastname;
property Age : Integer read FAge write FAge;
end;

三、双击并加入事件代码

1.创建一个对象实列Person

2.创建一个BindSourceAdapter

  • self,   指定TObjectBindSource的归属
  • MyPerson,需要邦定对象实例
  • True,是否自动释放,如果否则False 默认值为True
procedure TForm4.AdapterBindSource1CreateAdapter(Sender: TObject;
var ABindSourceAdapter: TBindSourceAdapter);
begin
MyPerson :=TPerson.Create('test','test1', );
ABindSourceAdapter := TObjectBindSourceAdapter<TPerson>.Create(Self, MyPerson, True);
end;

四、放一个TStringGrid对象 在Events LiveBindings点击BindVisually

点击运行

=====================================================

以下为原话

LiveBindings in XE3: TAdapterBindSource and binding to Objects

In the last post I introduced BindSources, a new set of classes in the LiveBinding system in RAD Studio XE3, and in particular, looked at TBindSourceDB. That’s fine if what you are binding to is a Dataset, but what happens if what you want to bind to is an object?

Binding to objects was possible in LiveBindings in XE2, and that approach will still work, however it doesn’t leverage all the LiveBinding Designer goodness.

Well, an easy answer would be “Do it the same way you did it in XE2″. Binding to objects was possible in LiveBindings in XE2, and that approach will still work, however it doesn’t leverage all the LiveBinding Designer goodness.

A better answer, if we want to both use the LiveBinding Designer and do the minimal amount of work, is to use another of the BindSource components: the TAdapterBindSource.

Whereas the TBindSourceDB acted as a gateway to allow us to connect the LiveBindings engine to fields in a dataset, a TAdapterBindSource allows us to connect it to elements in an Adapter. What’s an Adapter? Well, it’s a descendant of TBindSourceAdapter, who’s responsibility it is to take your custom data source (in this case an object) and make it available (ie. adapt it) to the TAdapterBindSource, and by extension, the LiveBinding engine.

An example is probably in order, then we’ll come back and drill in a bit further.

Create a new FireMonkey project (LiveBindings are available in VCL too), and in the form source define a new class like this:

type
TPerson = class
private
FAge: Integer;
FLastname: string;
FFirstname: string;
public
constructor Create(const Firstname, Lastname : string; Age : Integer); virtual;
property Firstname : string read FFirstname write FFirstname;
property Lastname : string read FLastname write FLastname;
property Age : Integer read FAge write FAge;
end;

The constructor, not surprisingly, is implemented like this:

constructor TPerson.Create(const Firstname, Lastname: string; Age : Integer);
begin
FFirstname := Firstname;
FLastname := Lastname;
FAge := Age;
end;

Note, I didn’t have to use properties to make this work, it works just as well with Fields. Old habits die hard I guess.

Also, add a private field to your form like so:

MyPerson : TPerson;

Next, drop a TAdapterBindSource on the form and put the following code in its OnCreateAdapter event:

procedure TForm4.AdapterBindSource1CreateAdapter(Sender: TObject;
var ABindSourceAdapter: TBindSourceAdapter);
begin
MyPerson := TPerson.Create('Fred', 'Flintstone', );
ABindSourceAdapter := TObjectBindSourceAdapter<TPerson>.Create(self, MyPerson, True);
end;

The first line is not that interesting: I’m creating an instance of our TPerson class. However it’s the second line where we encounter our first adapter. The OnCreateAdapter event has a var parameter of type TBindSourceAdapter called ABindSourceAdapter. I need to create an instance of a TBindSourceAdapter (usually of a descendant) and pass it back to the TAdapterBindSource via this var parameter.

That’s what the second line does. You can see we’re creating an instance of a generic TObjectBindSourceAdapter<T>, specifically a TObjectBindSourceAdapter<TPerson>. I’m passing the following values in to the constructor:

  • self, as the TObjectBindSource’s owner (it’s a TComponent descendant)
  • MyPerson, which is the instance of the TPerson I want to adapt.
  • True, indicating that I want to make the TObjectBindSourceAdapter responsible for freeing my TPerson instance (this is actually the default, but I included it here for completeness)

This is actually enough to get started. If you drop a Grid down on the form, drag a link between the * field in the AdapterBindSource to the * in the Grid in the LiveBindings Designer (see the bottom of the screenshot below) and run your app you should see the values of our Person instance in the Grid.

That’s useful as far as it goes, but there is a problem: I can’t see the Firstname, Lastname and Age properties in the LiveBindings Designer, which makes it a manual process to bind one of those values to say an Edit box or Label. We’ve cheated by using the * property of the AdapterBindSource but unless we’re happy using a grid to display a single TPerson, we’re going to need to solve this. (We’ll come back to collections of objects later, I promise)

To get the fields of my object to show up in the LiveBindings designer, we can leverage another new component in XE3, a TDataGeneratorAdapter.

To get the fields of my object to show up in the LiveBindings designer, we can leverage another new component in XE3, a TDataGeneratorAdapter. This is another TBindSourceAdapter descendant, and in fact this one is installed on the component palette (I did mention before that TBindSourceAdapters were TComponents). A TDataGeneratorAdapter allows you to define one or more fields in your adapter, along with an accompanying generator that will generate some format of values for your field, at both design time and run time if you like. Drop one onto your form and then bring up the property editor for the TDataGeneratorAdapter.FieldDefs property and have a look:

As you can see, there is a Booleans generator that will generate random boolean values, random currency generators, date generators for both TDate types and also strings containing date values. Scroll further down and there are even String and TStrings generators that will fill return Lorem Ipsum text.

Let’s create three fields to match the name and type of our TPerson object like so:

Now select your AdapterBindSource and set its Adapter property to point to our DataGeneratorAdapter component. Make sure the DataGeneratorAdapter is set to Active and at design time you should see something like this:

Not only do we have design-time data in our grid (courtesy of our generators), but we also now have the fields showing up in the LiveBinding Designer so we can start easily binding their values to other controls.

Because we still have the OnCreateAdapter event setup, and further, because the names of the fields we created in our DataGeneratorAdapter match the field names in our TPerson class, if we run the app now our DataGeneratorAdapter will be replaced as the adapter for the AdapterBindSource by our TObjectBindSourceAdapter, giving us an easy design-time experience while still giving us data from our object at runtime. If we removed this event, the AdapterBindSource would continue to use the DataGeneratorAdapter at runtime as well.

A few things to note here:

  • The DataGeneratorAdapter is creating these field values on the fly as requested, but once created they behave like a dataset. ie. you can edit them, post them, navigate around and they retain their values.
  • You could just as easily use the DataGeneratorAdapter when binding to a dataset. Let’s say you need to prototype a form for a table that does not yet exist. Use the DataGeneratorAdapter as above, show the prototype to the customer, and once they sign off on it then go ahead and build out the actually database table and datasets later. In fact there is another component included in XE3 called TPrototypeBindSource which is basically a combination of the TAdapterBindSource and the TDataGeneratorAdapter to make this scenario even easier. I plan on posting about this component in a future article, but in the meantime there is a tutorial available in the Help.

Now that we have fields showing up in the LiveBindings Designer, you can go ahead and replace the grid with components more appropriate for displaying a single object instance if you wish. You can do this either by adding the component to the form and dragging in the designer to create the link, or right-click on the fields in the designer and select “Bind to new control…”. (check out the previous article if you need a refresher)

However I’m going to leave the grid there, as I want to come good on the promise I made earlier: to look at binding to a collection of objects.

Let’s change the MyPerson field that we added to our form earlier to look like:

  MyPeople : TObjectList<TPerson>;

Then, go back into the source in your AdapterBindSource1.OnCreateAdapter event and change it to look like this:

procedure TForm4.AdapterBindSource1CreateAdapter(Sender: TObject;
var ABindSourceAdapter: TBindSourceAdapter);
begin
MyPeople := TObjectList<TPerson>.Create;
 
MyPeople.Add(TPerson.Create('Fred', 'Flintstone', ));
MyPeople.Add(TPerson.Create('Wilma', 'Flintstone', ));
MyPeople.Add(TPerson.Create('Barney', 'Rubble', ));
MyPeople.Add(TPerson.Create('Betty', 'Rubble', ));
 
ABindSourceAdapter := TListBindSourceAdapter<TPerson>.Create(self, MyPeople, True);
end;

You can see we’re creating a TObjectList, we’re adding a few instances to it, and then rather than creating a TObjectBindSourceAdapter, we’re creating a TListBindSourceAdapter. That’s all we need to do.

Run your app, and you should see the four TPerson instances we created in the grid. Further, if you right-click on the AdapterBindSource at designtime and add a Navigator, at runtime you can click the Insert button in the Navigator and it will add a new TPerson instance to our list, ready for editing.

That’s enough for this post, but we’re not quite done with this topic. Next post I want to look at editing the data in your objects, as using the Adapters in the way we just have raises a couple of interesting issues that aren’t immediately obvious (or at least they weren’t to me).

Further Reading

不爽的的是在设计期间不能知道对象有几个属性(FisrtName, LastName, Age在设计期间都看不见),

为了解决这个问题我们使用TDataGeneratorAdapter控件

一、拖入一个TDataGeneratorAdapter控件并点击Add Field

二、设计完成后连接StringGrid与TDataGeneratorAdapter绑定

到些设计已经完成,但我们仍然配置OnCreateAdapter事件 我们在DataGeneratorAdapter创建的字段匹配TPerson类 如果我们运行程序会通过 DataGeneratorAdapter通过TObjectBindSourceAdapter 替换成 AdapterBindSource,

如果我们不需要这个事件, AdapterBindSource会使用DataGeneratorAdapter也可以运行

NOTE:

   1.DataGeneratorAdapter类似DataSet 可以编辑、提交、保存

2.当需要一个DataSet时可以使用DataGeneratorAdapter

MyPeople : TObjectList<TPerson>;
procedure TForm1.AdapterBindSource1CreateAdapter(Sender: TObject;
var ABindSourceAdapter: TBindSourceAdapter);
begin
MyPeople := TObjectList<TPerson>.Create();
MyPeople.Add(TPerson.Create('Fred', 'Flintstone', ));
MyPeople.Add(TPerson.Create('Wilma', 'Flintstone', ));
MyPeople.Add(TPerson.Create('Barney', 'Rubble', ));
MyPeople.Add(TPerson.Create('Betty', 'Rubble', )); ABindSourceAdapter := TListBindSourceAdapter<TPerson>.Create(Self, MyPeople, True);
end;

LiveBindings如何绑定一个对象(转)的更多相关文章

  1. ListBox绑定一个对象

    转自原文 C#中ListBox的Items属性是Object对象,如何显示该对象的别名 而真正的则保存在其他的地方 一般是datasource 绑定一个list对象 list 可以是 自定义类型的对象 ...

  2. v-model绑定一个对象,组件内部分别负责不同字段的场景实现

    我们知道v-model对于单个property双向数据绑定非常有用,保持父子组件之间的数据传递和同步,但也有很多场景下希望一个组件能够处理多个数据字段,这时就有一些小小技巧了. https://sim ...

  3. Vue - class与style绑定

    1.通过v-bind绑定一个class A:直接绑定 B:通过v-bind绑定一个对象 C:绑定一个返回对象的计算属性 D:绑定一个数组对象 2.绑定内联样式 A:直接子啊属性名上面绑定 B:绑定到一 ...

  4. paip.提升效率---提升绑定层次--form绑定取代field绑定

    paip.提升效率---提升绑定层次--form绑定取代field绑定 =================== 编辑form中,常常需要,绑定一个对象到个form..   传统上要绑定field开始. ...

  5. vue 绑定样式的几种方式

    vue 绑定样式 对象语法 1.v-bind:class设置一个对象,动态切换class <div :class="{'active':isActive}">xxx&l ...

  6. wpf binging(三) 绑定方法的返回值

    有时候我们不能绑定对象的属性或者成员,我们需要绑定一个对象的方法时 可以用 ObjectDataProvider 比如先声明一个类 含有加法 ObjectDataProvider 的简单使用 以下为综 ...

  7. vue绑定html的class属性的方法

    一.对象语法绑定class属性 class的属性代码如下 <style type="text/css"> .red{ color: red; width: 100px; ...

  8. 下拉列表框DropDownList绑定Dictionary泛型类

    DropDownList绑定Dictionary泛型类 定义一个Dictionary泛型类 /// <summary>    /// 产品类型    /// </summary> ...

  9. Vue.js学习笔记 第二篇 样式绑定

    Class绑定的对象语法 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

随机推荐

  1. guxh的python笔记六:类的属性

    1,私有属性 class Foo: def __init__(self, x): self.x = x 类的属性在实例化之后是可以更改的: f = Foo(1) print(f.x) # 1 f.x ...

  2. 注册COMDLG32.OCX方法

    1.将下载的comdlg32.ocx文件拷贝到C:\Windows\SysWOW64(32位电脑为C:\Windows\System32)文件夹中. 2.按win+x打开快捷命令选项菜单: 再按“A” ...

  3. Python 同一文件中,有unittest不执行“if __name__ == '__main__”,不生成HTMLTestRunner测试报告的解决方案

    1.问题:Python中同一个.py文件中同时用unittest框架和HtmlReport框架后,HtmlReport不被执行. 2.为什么?其实不是HtmlReport不被执行,也不是HtmlRep ...

  4. 一次完整的http事务的过程

    1.域名解析 2.发起TCP三次握手 3.建立TCP连接以后发起http请求 4.服务器端响应请求,浏览器得到html代码 5.浏览器解析html代码并请求html中的资源 6.浏览器对页面进行渲染呈 ...

  5. 第一个博客——python通过值传递函数参数

    功能:银行账户计算利率(python实现) 部分代码: def addInterest(balance, rate): newBalance = balance * (1 + rate) balanc ...

  6. MapServer Tutorial——MapServer7.2.1教程学习——教程背景

    MapServer Tutorial——MapServer7.2.1教程学习——教程背景 一.前言 目前处于MapServer学习入门阶段,所以每一步都需要打下扎实基础.尽自己最大的努力,去学习知识的 ...

  7. 正确学习Linux系统的5个建议

    摘要: 最近几年Linux系统应用越来越广泛,以至于很多人开始热衷学习Linux.但是我们都是从小都是学习windows系统长大的,从windows 98到现在的windows 10,而根据学习win ...

  8. .net core 使用log4net日志组件

    一个web站点必须要记录日志,否则哪里出错了,完全是黑娃找黑妹,两眼一抹黑. 最常用的就是log4net日志组件.我们可以通过扩展加入日志组件. 第一步:在项目中NuGet log4net包,即 In ...

  9. redis不重启,切换RDB备份到AOF备份

    确保redis版本在2.2以上 [root@pyyuc /data ::]#redis-server -v Redis server v= sha=: malloc=jemalloc- bits= b ...

  10. Tomcat和java的安装

    java开发环境搭建1.将普通用户添加到sudoers中    进入root模式        编辑添加            visudo            username ALL=(ALL) ...