2016-07-29 8 views
2

I definierte die nachfolgende Einheit für die GeschäftslogikDelphi Livebinding Objekt und Combobox oder Radio-Buttons

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. 

Jetzt entwirft ich ein Formular zum Bearbeiten eines TPerson, mit drei TEdit und TComboBox das Geschlecht auszuwählen.

Wie kann ich bidirektionale Lebendbindung für TCombobox verwenden?

Antwort

0

Da die Livebindings zwischen compless Klassen und Kontrollen mit Delphi ist nicht einfach, zu vereinfachen, dachte ich es angebracht, die TPerson Klasse wie folgt zu ändern:

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; 
... 

Im Folgenden ich für TPerson einen Adapter definiert:

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; 

auf einem Formular I eine TBindingList (BindingList1) fallen gelassen, eine TAdapterBindSource (PersonABS), ein TPersonsAdapter (PersonsAdapter) und 4 TRadioButton;

als Set

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'; 

Auf jeder TRadioButton setzen das Ereignis onClick wie folgt:

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; 

das ist alles.

Ich hoffe, dass die Lösung ausreichend robust und einfacher zu wiederholen ist.

0

Wenn Sie eine TComboBox anstelle von TRadioButtons verwenden, gehen wir auf diese Weise vor. Ich ziehe einen Adapter für TSexOfPerson Klasse zu erstellen:

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; 

auf einem Formular einen TBindingList fallen (BindingList1), eine TAdapterBindSource (PersonABS), einen TPersonsAdapter (PersonsAdapter1), eine TAdapterBindSource (SexOfPersonABS), ein TSexOfPersonsAdapter (SexOfPersonsAdapter1) und eine TComboBox (ComboBox1).

als gesetzt

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; 

öffnen Livebindings Designer und Link SexOfPersonABS.Description zu ComboBox1.Item.Text und SexOfPersonABS.Index zu ComboBox1.Item.LookupData, das einen TLinkFillPropertyToField (LinkFillControlToField1) geschaffen werden; verknüpfen Sie auch die PersonABS.Sex-Eigenschaft mit ComboBox1.SelectedValue.

Sie folgende Einstellungen vor:

LinkFillControlToField1.Control = ComboBox1; 
LinkFillControlToField1.DataSource = PersonABS; 
LinkFillControlToField1.FieldName = 'Sex'; 

LinkFillControlToField1.FillDataSource = SexOfPersonABS; 
LinkFillControlToField1.FillDisplayFieldName = 'Description'; 
LinkFillControlToField1.FillValueFieldName = 'Index'; 

Auf ComboBox1 OnChange eingestellt als

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; 

folgen das ist alles.