Delphi Livebinding对象和组合框或单选按钮



我为业务逻辑定义了后续单元

unit Models.Person;
interface
Type
  TPersonGender = (pgUndefined, pgMale, pgFemale, pgNotApplicable);
  TSexOfPerson = class(TPersistent)
  private
    FGender : TPersonGender;
  protected
    function GetDescription : string;
    function GetCode : string;
    function GetIndex : integer;
  public
    constructor Create; overload;
    constructor Create(const aValue : TGenderPerson); overload;
    procedure Assign(Source: TPersistent); override;
    property Gender : TGenderPerson read FGender write FGender;
    property Description : string read GetDescription;
    property Code : string read GetCode;
    property Index : integer read GetIndex;
  end;
  TPerson = class(TPersistent)
  private
    FSex : TSexOfPerson;
    FName : string;
    FSurName : string;
    FAddress : string;
  protected
    function GetSex : TPersonGender;
    procedure SetSex(aGender : TPersonGender);
  public
    constructor Create; overload;
    constructor Create(const aValue : TPerson); overload;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    property Name : string read FName write FName;
    property SurName : string read FSurName write FSurName;
    property Address : string read FAddress write FAddress;
    property Sex : TPersonGender read GetSex write SetSex
  end;
implementation
{ TSexOfPerson }
constructor TSexOfPerson.Create;
begin
  inherited Create;
  FGender := pgUndefined;
end;
constructor TSexOfPerson.Create(const aValue : TPersonGender);
begin
  inherited Create;
  FGender := aValue
end;
procedure TSexOfPerson.Assign(Source: TPersistent);
begin
  if Source is TSexOfPerson then
    FGender := TSexOfPerson(Source).Gender
  else
    inherited Assign(Source)
end;
function TSexOfPerson.GetDescription;
begin
  case FGender of
    pgUndefined : Result := '<Undefined>';
    pgMale : Result := 'Male';
    pgFemale : Result := 'Female';
    pgNotApplicable : Result := '<Not applicable>';
  end
end;
function TSexOfPerson.GetIndex;
begin
  Result := Ord(FGender)
end;
function TSexOfPerson.GetCodice;
begin
  case FGender of
    pgUndefined : Result := '';
    pgMale : Result := 'M';
    pgFemale : Result := 'F';
    pgNotApplicable : Result := 'N'
  end
end;
{ TPerson }
constructor TPerson.Create;
begin
  inherited Create;
  FSex := TSexOfPerson.Create(pgUndefined)
end;
constructor TPerson.Create(const aValue : TPerson);
begin
  inherited Create;
  FSex := TSexOfPerson.Create(aValue)
end;
destructor TPerson.Destroy;
begin
  FSex.Free;
  inherited Destroy
end;
procedure TPerson.Assign(Source: TPersistent);
begin
  if Source is TPerson then
  begin
    FName := TPerson(Source).Name;
    FSurName := TPerson(Source).SurName;
    FAddress := TPerson(Source).Address;
    FSex.Gender := TPerson(Source).Sex;
  end
  else
    inherited Assign(Source)
end;
function GetSex : TPersonGender;
begin
  Result := FSex.Gender
end;
procedure SetSex(aGender : TPersonGender);
begin
  if FSex.Gender <> aGender then
    FSex.Gender := aGender
end;
end.

现在我将设计一个表格来编辑一个TPerson,用三个TEdit和一个TCombox来选择性别。

如何使用TCombox的双向直播绑定?

鉴于完整类和控件之间的livebindings在Delphi中并不容易,为了简化,我认为如下更改TPerson类是合适的:

TPerson = class(TPersistent)
  private
    FSex : TSexOfPerson;
    FName : string;
    FSurName : string;
    FAddress : string;
  protected
    function GetSex : TPersonGender;
    procedure SetSex(aGender : TPersonGender);
  public
    constructor Create; overload;
    constructor Create(const aValue : TPerson); overload;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    property Name : string read FName write FName;
    property SurName : string read FSurName write FSurName;
    property Address : string read FAddress write FAddress;
    property Sex : integer read GetSex write SetSex
  end;
implementation
...
function TPerson.GetSex : integer;
begin
  Result := FSex.Index
end;
procedure TPerson.SetSex (aValue : integer);
begin
  if FSex.Integer <> aValue then
    case aValue of
    0 : FSex.MtsSesso := pgUndefined;
    1 : FSex.MtsSesso := pgMale;
    2 : FSex.MtsSesso := pgFemale;
    3 : FSex.MtsSesso := pgNotApplicable;
    end;
end;
procedure TPerson.Assign(Source: TPersistent);
begin
  if Source is TPerson then
  begin
    FName := TPerson(Source).Name;
    FSurName := TPerson(Source).SurName;
    FAddress := TPerson(Source).Address;
    case TPerson(Source).Sex of
    0 : FSex.MtsSesso := pgUndefined;
    1 : FSex.MtsSesso := pgMale;
    2 : FSex.MtsSesso := pgFemale;
    3 : FSex.MtsSesso := pgNotApplicable;
    end;
  end
  else
    inherited Assign(Source)
end;
...

在下文中,我为TPerson定义了一个适配器:

type
  TPersonsAdapter = class(TListBindSourceAdapter<TPerson>)
  public
    constructor Create(AOwner: TComponent); override;
  end;
  procedure Register;
...
constructor TPersonsAdapter.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  //load Persons list
  SetList(LoadPersons)
end;
procedure Register;
begin
  RegisterComponents('CustomAdapters', [TPersonsAdapter]);
end;

在一张表格上,我放下了一个TBindingList(BindingList1)、一个TAdapterBindSource(PersonABS)、一台TPersonadapter(PersonsAdapter)和4个TRadioButton;

比设置

PersonABS.Adapter := PersonsAdapter;
PersonABS.OnCreateAdapter := PersonABSCreateAdapter;
procedure TForm1.PersonABSCreateAdapter(Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter);
begin
  ABindSourceAdapter := TObjectBindSourceAdapter<TPerson>.Create(PersonABS, CurrentPerson, False);
  ABindSourceAdapter.AutoPost := True;
end;
On BindingList1 component, create 4 TLinkPropertyToField one for each radiobutton and set the following as:
LinkPropertyToField1.Component := RadioButton1;
LinkPropertyToField1.ComponentProperty := IsChecked
LinkPropertyToField1.CustomFormat := 'IfThen(%s=0, True, False)';
LinkPropertyToField1.DataSource := PersonABS;
LinkPropertyToField1.FieldName := 'Sex';
LinkPropertyToField2.Component := RadioButton2;
LinkPropertyToField2.ComponentProperty := IsChecked
LinkPropertyToField2.CustomFormat := 'IfThen(%s=1, True, False)';
LinkPropertyToField2.DataSource := PersonABS;
LinkPropertyToField2.FieldName := 'Sex';
LinkPropertyToField3.Component := RadioButton3;
LinkPropertyToField3.ComponentProperty := IsChecked
LinkPropertyToField3.CustomFormat := 'IfThen(%s=2, True, False)';
LinkPropertyToField3.DataSource := PersonABS;
LinkPropertyToField3.FieldName := 'Sex';
LinkPropertyToField4.Component := RadioButton4;
LinkPropertyToField4.ComponentProperty := IsChecked
LinkPropertyToField4.CustomFormat := 'IfThen(%s=3, True, False)';
LinkPropertyToField4.DataSource := PersonABS;
LinkPropertyToField4.FieldName := 'Sex';

在每个TRadioButton上,将事件设置为点击,如下所示:

procedure TForm1.RadioButton1Click(Sender: TObject);
begin
   if not TRadioButton(Sender).IsChecked then
     CurrentPerson.Sex := Ord(pgUndefined)
end;
procedure TForm1.RadioButton2Click(Sender: TObject);
begin
   if not TRadioButton(Sender).IsChecked then
     CurrentPerson.Sex := Ord(pgMale)
end;
procedure TForm1.RadioButton3Click(Sender: TObject);
begin
   if not TRadioButton(Sender).IsChecked then
     CurrentPerson.Sex := Ord(pgFemale)
end;
procedure TForm1.RadioButton4Click(Sender: TObject);
begin
   if not TRadioButton(Sender).IsChecked then
     CurrentPerson.Sex := Ord(pgNotApplicable)
end;

仅此而已。

我希望该解决方案足够有力,更容易重申。

如果您使用TComboBox而不是TRadioButtons,我们将按此方式进行。我更喜欢为TSexOfPerson类创建适配器:

type
  TSexOfPersonsAdapter = class(TListBindSourceAdapter<TSexOfPerson>)
  public
    constructor Create(AOwner: TComponent); override;
  end;
  procedure Register;
...
constructor TSexOfPersonsAdapter.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  //load Sex Persons list
  SetList(LoadSexOfPerson)
end;
procedure Register;
begin
  RegisterComponents('CustomAdapters', [TSexOfPersonsAdapter]);
end;
function LoadSexOfperson: TList<TSexOfPerson>;
begin
  Result := TObjectList<TSexOfPerson>.Create;
  Result.Add(TSexOfPerson.Create(pgUndefined));
  Result.Add(TSexOfPerson.Create(pgMale));
  Result.Add(TSexOfPerson.Create(pgFemale));
  Result.Add(TSexOfPerson.Create(pgNotApplicable));
end;

在表单上放置TBindingList(BindingList1)、TAdapterBindSource(PersonABS)、TPersonadapter(PersonsAdapter1)、TADdapterBindSourceSexOfPersonABS、TSexOfPersonsAdapter SexOfpersonsAdapter 1和TComboBox(ComboBox1)。

比设置

SexOfPersonABS.Adapter = SexOfPersonsAdapter1;
PersonABS.Adapter = PersonsAdapter1;
PersonABS.OnCreateAdapter = PersonABSCreateAdapter;
procedure TForm1.PersonABSCreateAdapter(Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter);
begin
  ABindSourceAdapter := TObjectBindSourceAdapter<TPerson>.Create(PersonABS, CurrentPerson, False);
  ABindSourceAdapter.AutoPost := True;
end;

打开livebindings设计器,将SexOfPersonABS.Description链接到ComboBox1.Item.Text,将SexOfPersonABS.Index链接到ComboBox1.Item.LookupData,这将创建一个TLinkFillPropertyToField(LinkFillControlToField1);还将PersonABS.Sex属性链接到ComboBox1.SelectedValue.

设置以下内容:

LinkFillControlToField1.Control    = ComboBox1;
LinkFillControlToField1.DataSource = PersonABS;
LinkFillControlToField1.FieldName  = 'Sex';
LinkFillControlToField1.FillDataSource = SexOfPersonABS;
LinkFillControlToField1.FillDisplayFieldName = 'Description';
LinkFillControlToField1.FillValueFieldName = 'Index';

在ComboBox1上将OnChange设置为如下

procedure TForm1.ComboBox1Change(Sender: TObject);
var
  aValue : TValue;
begin
  aValue := LinkFillControlToField1.BindList.GetSelectedValue;
  case aValue.AsInteger of
  Ord(pgUndefined)     : CurrentPerson.Sex := Ord(pgUndefined);
  Ord(pgMale)          : CurrentPerson.Sex := Ord(pgMale);
  Ord(pgFemale)        : CurrentPerson.Sex := Ord(pgFemale);
  Ord(pgNotApplicable) : CurrentPerson.Sex := Ord(pgNotApplicable);
  end
end;

仅此而已。

相关内容

  • 没有找到相关文章

最新更新