使用TListView绑定对象

时间:2016-08-04 09:43:12

标签: delphi data-binding livebindings

我最近发现了Data Bindings,并关注this great tutorial about data binding and Delphi。我使用了TEdit,但现在我有一个TObjectList,我实现了绑定它们,但它只能以一种方式工作。当我修改TObjectList时,它会更改ListView,但是当我修改ListView时:它不会更改TOBjectList

这是我的代码:

// When I change an Item of my ListView
procedure TForm1.ListView1Change(Sender: TObject; Item: TListItem;
  Change: TItemChange);
begin
  TBindings.Notify(Sender, 'Items.Item[' + IntToStr(Item.Index) +   '].Caption');
end;

// When I add a new item to my TListView, and I want that to be bound with my ListView
itemAdd := ListView1.Items.Add;
Item.Bind('id', ListView1, 'Items.Item[' + IntToStr(ListView1.Items.Count-1) + '].Caption');



  // The TBoundObject Class. Every class thatI want to bind with UI, inherits from this class
  unit U_TBoundObject;

  interface

  uses
    Generics.Collections, System.Bindings.Expression, System.Bindings.Helper;

  type
    TBoundObject = class
    protected
      type
        TExpressionList = TObjectList<TBindingExpression>;
    private
      FBindings: TExpressionList;
    protected
      procedure Notify(const APropertyName: string = '');
      property Bindings: TExpressionList read FBindings;
    public
      constructor Create; virtual;
      destructor Destroy; override;
      procedure Bind(const AProperty: string; const ABindToObject: TObject;
          const ABindToProperty: string; const ACreateOptions:
          TBindings.TCreateOptions = [coNotifyOutput, coEvaluate]);
      procedure ClearBindings;
    end;

  implementation

  constructor TBoundObject.Create;
  begin
    inherited;
    FBindings := TExpressionList.Create(false {AOwnsObjects});
  end;

  destructor TBoundObject.Destroy;
  begin
    ClearBindings;
    FBindings.Free;
    inherited;
  end;

  procedure TBoundObject.ClearBindings;
  var
    i: TBindingExpression;
  begin
    for i in FBindings do
      TBindings.RemoveBinding(i);
    FBindings.Clear;
  end;

  procedure TBoundObject.Notify(const APropertyName: string);
  begin
    TBindings.Notify(Self, APropertyName);
  end;

  procedure TBoundObject.Bind(const AProperty: string;
    const ABindToObject: TObject; const ABindToProperty: string;
    const ACreateOptions: TBindings.TCreateOptions);
  begin
    // From source to dest
    FBindings.Add(TBindings.CreateManagedBinding(
        { inputs }
        [TBindings.CreateAssociationScope([Associate(Self, 'src')])],
        'src.' + AProperty,
        { outputs }
        [TBindings.CreateAssociationScope([Associate(ABindToObject, 'dst')])],
        'dst.' + ABindToProperty,
        nil, nil, ACreateOptions));
    // From dest to source
    FBindings.Add(TBindings.CreateManagedBinding(
        { inputs }
        [TBindings.CreateAssociationScope([Associate(ABindToObject, 'src')])],
        'src.' + ABindToProperty,
        { outputs }
        [TBindings.CreateAssociationScope([Associate(Self, 'dst')])],
        'dst.' + AProperty,
        nil, nil, ACreateOptions));
  end;

  end.

1 个答案:

答案 0 :(得分:1)

我知道你要做什么,但你并没有真正去做。

实际上,您正在尝试绑定两个对象的属性,但是您正在处理子属性(属性的属性),就好像它是属性一样。你说它可以单向运行,但对我来说它并没有。

通过直接(而不是间接)处理对象,它变得更加容易。

这是我添加和关联相关对象的方式

procedure TForm2.SpeedButtonAddClick(Sender: TObject);
var
  ItemAdd : TListItem;
  Item : TFeature;
begin
  Item := TFeature.Create;
  fObjectList.Add( Item );
  ItemAdd := ListView1.Items.Add;
  Item.Bind('id', ItemAdd, 'Caption');
end;

这是对象更改的代码

procedure TFeature.SetID(const Value: string);
begin
  if fID <> Value then // prevent an infinite loop
  begin
    fID := Value;
    TBindings.Notify( self, 'id' );
  end;
end;

(测试是为了防止两个对象不断相互更新)

这是ItemView更改的代码

procedure TForm2.ListView1Change(Sender: TObject; Item: TListItem;
  Change: TItemChange);
begin
  TBindings.Notify(Item, 'Caption');
end;

我已经测试了它,它可以在两个方向上工作。