2016-08-04 6 views
1

Недавно я обнаружил Data Bindings и последовал за this great tutorial about data binding and Delphi. Я сделал это с TEdit, но теперь у меня есть TObjectList, и я добился их привязки, но он работает только одним способом. Когда я изменяю свой TObjectList, он меняет ListView, но когда я изменяю ListView: он не изменит TOBjectList.Связывание объекта с TListView

Вот мой код:

// 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. 
+0

Я не думаю, что вы показали нам достаточно здесь. Можете ли вы опубликовать минимальный проверяемый код, что-то, что мы можем скомпилировать и попробовать сами. (Фактический полный код, вероятно, заполняет счет, если он не слишком длинный). – Dsm

+0

Привет, на самом деле мой код довольно длинный, и я действительно не знаю, что я мог бы добавить ... Lemme попробуйте связанный класс! –

+0

Это VCL или FMX? Думаю, ваш список объектов - это что-то вроде TObjectList ? – Dsm

ответ

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; 

Я тестировал его, и он работает в обоих направлениях.

+0

Привет, человек. Хорошо, спасибо! Он работает так, как я хотел :) –

Смежные вопросы