3

I have been trying to make a test object that has a string property visible to the visual binding form. The component is registered with the appropriate properties. Using XE8 and Firemonkey.

I can get it to show on the visual binder by selecting it using the hide show elements, however I cannot get it to bind the Foo string to a TEdit text property, the readonly (which does nothing yet) will bind to the Text Property.

  • how do I get it show in it with default class visibility
  • why doesn't the Foo string bind to the text property

The help files are a little thin on this. I guessing I'm missing something really simple here.

Object Code is below.

Thanks.

unit TestOBj;

interface

uses
  System.Classes, System.SysUtils, System.StrUtils, Data.Bind.Components;

Type

  TMyLBObject = Class (TComponent)
  private
    fFooString:String;
    FReadOnly: Boolean;
    procedure SetReadOnly(const Value: Boolean);
    procedure SetFooString(const Value: String);
  protected
    function CanObserve(const ID: Integer): Boolean; override;                       
    procedure ObserverAdded(const ID: Integer; const Observer: IObserver); override;
    procedure ObserverToggle(const AObserver: IObserver; const Value: Boolean);
  published
    property Foo:String read FFooString write SetFooString;
    property ReadOnly:Boolean read FReadOnly write SetReadOnly;
  End;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Test', [TMyLBObject]);
end;

{ TMyLBObject }

function TMyLBObject.CanObserve(const ID: Integer): Boolean;
begin
  Result := False;
  if ID = TObserverMapping.EditLinkID then
    Result := True;
  if ID = TObserverMapping.ControlValueID then
    Result := True;
end;

procedure TMyLBObject.ObserverAdded(const ID: Integer;
  const Observer: IObserver);
begin
  if ID = TObserverMapping.EditLinkID then
    Observer.OnObserverToggle := ObserverToggle;
end;


procedure TMyLBObject.ObserverToggle(const AObserver: IObserver;
  const Value: Boolean);
var
  LEditLinkObserver: IEditLinkObserver;
  LSaveReadOnly: Boolean;
begin
  if Supports(AObserver, IEditLinkObserver, LEditLinkObserver) then
  begin
    if Value then
    begin
      LSaveReadOnly := ReadOnly;
      if LEditLinkObserver.IsReadOnly then
        ReadOnly := True;
      FReadOnly := LSaveReadOnly;
    end
    else
      if not (csDestroying in ComponentState) then
        ReadOnly := FReadOnly;
  end;
end;


procedure TMyLBObject.SetFooString(const Value: String);
begin
  FFooString := Value;
end;

procedure TMyLBObject.SetReadOnly(const Value: Boolean);
begin
  FReadOnly := Value;
end;


initialization
  RegisterClass(TMyLBObject);
  RegisterObservableMember(TArray<TClass>.Create(TMyLBObject), 'Foo', 'FMX');
finalization
  UnRegisterObservableMember(TArray<TClass>.Create(TMyLBObject));
end.
Yandros
  • 65
  • 1
  • 4

1 Answers1

4

Your TMyLBObject component does not have an [ObservableMember('Foo')] attribute.

type
  [ObservableMember('Foo')] // <-- add this
  TMyLBObject = Class (TComponent)
    ...
  published
    property Foo:String read FFooString write SetFooString;
    ...
  End;

See the example in the documentation:

Tutorial: Creating LiveBindings-Enabled Components.

Which includes this note:

The ObservableMember attribute will be used by LiveBindings components to generate expressions. RegisterObserverableMember() will be used at design time to inform the LiveBindings Designer.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks that's got the Foo property visible without having to go and tick the box. Now this is the one that really has me confused, Why can I not bind the Foo property to a TEdit text property. String <-> String seems the most logical thing. – Yandros Aug 12 '15 at 23:01
  • What does your LiveBinding setup look like in your project? Are you using the LiveBinding wizard, or a data source like `TPrototypeBindSource`, or what are you actually doing? Are you able to bind other component properties to the `TEdit.Text` property? I don't use LiveBindings or FireMonkey, so I don't know how well they work together. – Remy Lebeau Aug 12 '15 at 23:30
  • Thanks for the help btw. I'm using the livebinding wizard, its a simple form with a tedit and the TmyLBObj, Interestingly I can actually get the binding wizard to bind from the Tedit.text -> TmyLBObject.Foo, but not the other way. So the binding is unidirectional and only valid to the Foo Property, not from it. All getting to hard, maybe I should do the binding in code at runtime. this is an early foray into livebinding, moving from VCL to FMX!! – Yandros Aug 13 '15 at 00:48
  • If you create a LiveBinding on the `TMyLBObject` component, you can link the `TEdit.Text` property to update the `TMyLBObject.Foo` property. Have you created a LiveBinding on the `TEdit` component to link its `Text` property to be updated from `TLBObject.Foo`? Again, what are the EXACT steps you are taking to set up the LiveBinding in your app once the components are dropped on your Form? – Remy Lebeau Aug 13 '15 at 01:38
  • In the livebinding designer, left click on the MyObj Foo property and drag to the Tedit Text property, it creates a uni directional link from text -> Foo. I need it to be bidirectional. Found an old blog by Damien Bootsma but it uses TBindScope (which is no longer a design time object). – Yandros Aug 13 '15 at 02:27