delphidata-bindingdelphi-11-alexandria

Is there a Bug in Delphi when using Visual Binding combined with FDQuery and OnClick event of involved component?


When you connect a FDQuery via LiveBinding to edits and a switscher, the switcher IsCheched state changes, when you change other connected Data in the Query.

For better Understanding here is an Example: Code for uMain.fmx file:

object MainForm: TMainForm
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 704
  ClientWidth = 560
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  OnCreate = FormCreate
  DesignerMasterStyle = 0
  object edt_FirstValue: TEdit
    Touch.InteractiveGestures = [LongTap, DoubleTap]
    Align = MostTop
    TabOrder = 1
    Position.X = 10.000000000000000000
    Position.Y = 10.000000000000000000
    Margins.Left = 10.000000000000000000
    Margins.Top = 10.000000000000000000
    Margins.Right = 10.000000000000000000
    Margins.Bottom = 10.000000000000000000
    Size.Width = 540.000000000000000000
    Size.Height = 22.000000000000000000
    Size.PlatformDefault = False
  end
  object edt_SecondValue: TEdit
    Touch.InteractiveGestures = [LongTap, DoubleTap]
    Align = MostTop
    TabOrder = 0
    Position.X = 10.000000000000000000
    Position.Y = 99.000000000000000000
    Margins.Left = 10.000000000000000000
    Margins.Top = 10.000000000000000000
    Margins.Right = 10.000000000000000000
    Margins.Bottom = 10.000000000000000000
    Size.Width = 540.000000000000000000
    Size.Height = 22.000000000000000000
    Size.PlatformDefault = False
  end
  object Switch1: TSwitch
    Align = MostTop
    IsChecked = False
    Margins.Left = 10.000000000000000000
    Margins.Top = 10.000000000000000000
    Margins.Right = 10.000000000000000000
    Margins.Bottom = 10.000000000000000000
    Position.X = 10.000000000000000000
    Position.Y = 52.000000000000000000
    Size.Width = 540.000000000000000000
    Size.Height = 27.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 7
    OnClick = Switch1Click
  end
  object FDMemTable1: TFDMemTable
    Active = True
    FieldDefs = <
      item
        Name = 'FirstValue'
        DataType = ftString
        Size = 255
      end
      item
        Name = 'SecondValue'
        DataType = ftString
        Size = 255
      end
      item
        Name = 'SwitcherState'
        DataType = ftBoolean
      end>
    IndexDefs = <>
    FetchOptions.AssignedValues = [evMode]
    FetchOptions.Mode = fmAll
    ResourceOptions.AssignedValues = [rvSilentMode]
    ResourceOptions.SilentMode = True
    UpdateOptions.AssignedValues = [uvCheckRequired, uvAutoCommitUpdates]
    UpdateOptions.CheckRequired = False
    UpdateOptions.AutoCommitUpdates = True
    LocalSQL = FDLocalSQL1
    StoreDefs = True
    Left = 192
    Top = 352
  end
  object FDConnection1: TFDConnection
    Params.Strings = (
      'DriverID=SQLite')
    Connected = True
    LoginPrompt = False
    Left = 200
    Top = 448
  end
  object FDLocalSQL1: TFDLocalSQL
    Connection = FDConnection1
    Active = True
    DataSets = <>
    Left = 88
    Top = 456
  end
  object FDPhysSQLiteDriverLink1: TFDPhysSQLiteDriverLink
    Left = 352
    Top = 448
  end
  object FDQuery1: TFDQuery
    Active = True
    LocalSQL = FDLocalSQL1
    Connection = FDConnection1
    SQL.Strings = (
      'select * from FDMemtable1')
    Left = 360
    Top = 360
  end
  object BindSourceDB1: TBindSourceDB
    DataSet = FDQuery1
    ScopeMappings = <>
    Left = 264
    Top = 336
  end
  object BindingsList1: TBindingsList
    Methods = <>
    OutputConverters = <>
    Left = 20
    Top = 5
    object LinkControlToField1: TLinkControlToField
      Category = 'Schnelle Bindungen'
      DataSource = BindSourceDB1
      FieldName = 'FirstValue'
      Control = edt_FirstValue
      Track = False
    end
    object LinkControlToField2: TLinkControlToField
      Category = 'Schnelle Bindungen'
      DataSource = BindSourceDB1
      FieldName = 'SecondValue'
      Control = edt_SecondValue
      Track = False
    end
    object LinkControlToField3: TLinkControlToField
      Category = 'Schnelle Bindungen'
      DataSource = BindSourceDB1
      FieldName = 'SwitcherState'
      Control = Switch1
      Track = True
    end
  end
end

Code for uMain.pas:

unit uMain;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS,
  FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.UI.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.FMXUI.Wait, Data.DB,
  FireDAC.Stan.ExprFuncs, FireDAC.Phys.SQLiteWrapper.Stat, FireDAC.Phys.SQLiteDef, FireDAC.Phys.SQLite, FireDAC.Comp.Client, FireDAC.Phys.SQLiteVDataSet,
  FireDAC.Comp.DataSet, FMX.Controls.Presentation, FMX.Edit, FireDAC.DApt, FMX.StdCtrls, System.Rtti, System.Bindings.Outputs, FMX.Bind.Editors,
  Data.Bind.EngExt, FMX.Bind.DBEngExt, Data.Bind.Components, Data.Bind.DBScope, Data.Bind.Controls, FMX.Layouts, FMX.Bind.Navigator;

type
  TMainForm = class(TForm)
    edt_FirstValue: TEdit;
    edt_SecondValue: TEdit;
    FDMemTable1: TFDMemTable;
    FDConnection1: TFDConnection;
    FDLocalSQL1: TFDLocalSQL;
    FDPhysSQLiteDriverLink1: TFDPhysSQLiteDriverLink;
    FDQuery1: TFDQuery;
    Switch1: TSwitch;
    BindSourceDB1: TBindSourceDB;
    BindingsList1: TBindingsList;
    LinkControlToField1: TLinkControlToField;
    LinkControlToField2: TLinkControlToField;
    LinkControlToField3: TLinkControlToField;
    procedure FormCreate(Sender: TObject);
    procedure Switch1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.fmx}

procedure TMainForm.FormCreate(Sender: TObject);
begin
  FDQuery1.Append;
  FDQuery1.FieldByName('FirstValue').AsString := 'First Value, when you click the switcher it should be copyed to the next field';
  FDQuery1.FieldByName('SwitcherState').AsBoolean := false;
end;

procedure TMainForm.Switch1Click(Sender: TObject);
begin
  if Switch1.IsChecked then
    showmessage('You clicked me and my isChecked is TRUE');

  FDQuery1.FieldByName('SecondValue').AsString := edt_FirstValue.Text;

  if Switch1.IsChecked then
    showmessage('It is TRUE like expected')
  else
    showmessage('But now you changed a Field that is connected with visual Binding. IsChecked is FALSE now IMHO because Livebinding sets back the Value to the original State, and you see a short flicker in switch after close this Message');
end;

end.

I Would expect, that the Switcher stays the same after, but I think the on ClickEvent accours, before the Changed switcher State is written back into the Database.

Edit: Open a Bug report to Embarcadero. https://quality.embarcadero.com/browse/RSP-42074


Solution

  • Bug is fixed from RSP-42074 in Delphi 12.1 Alexandria