Question

J'ai souvent besoin de concevoir une boîte de dialogue dans Delphi / C ++ Builder qui permette de modifier diverses propriétés d'un objet, et le code à utiliser ressemble généralement à ceci.

Dialog.Edit1.Text := MyObject.Username;
Dialog.Edit2.Text := MyObject.Password;
// ... many more of the same

if (Dialog.ShowModal = mrOk) 
begin
  MyObject.Username := Dialog.Edit1.Text;
  MyObject.Password := Dialog.Edit2.Text;
  // ... again, many more of the same
end;

J'ai également souvent besoin d'un code similaire pour le classement des objets vers / depuis xml / ini-files / que ce soit.

Existe-t-il des expressions ou techniques communes permettant d'éviter ce type de code simple mais répétitif?

Était-ce utile?

La solution

eh bien, quelque chose qui me semble tout à fait précieux est l’assistant GExperts du plugin " Reverse Statement " qui est appelé après avoir installé GExperts en appuyant sur Maj + ALT + R

Ce qu'il fait est de changer automatiquement les assignations pour le bloc en surbrillance. Par exemple:

edit1.text := dbfield.asString;

devient

dbField.asString := edit1.text;

Ce n'est pas exactement ce que vous recherchez, mais un gain de temps considérable lorsque vous avez un grand nombre de missions.

Autres conseils

Voici ma variation à ce sujet. Ce que j'ai fait, après en avoir marre du même code répétitif, a été de nommer toutes les zones d'édition en fonction des noms de nœud XML que je voulais, puis de parcourir les composants et de générer leurs valeurs. Le code XML doit être évident, et je ne dispose que d’une boîte de dialogue et d’une case à cocher, mais vous devriez pouvoir voir l’idée.

procedure TfrmFTPSetup.LoadFromXML(szFileName : string);
var
xComponent : TComponent;
nLoop : Integer;
xMainNode : TXmlNode;
xDocument : TNativeXml;
begin
inherited;

xDocument := TNativeXml.Create;
try
    xDocument.LoadFromFile(szFileName);
    xMainNode := xml_ChildNodeByName(xDocument.Root, 'options');
    for nLoop := 0 to ComponentCount - 1 do
    begin
        xComponent := Components[nLoop];
        if xComponent is TRzCustomEdit then
        begin
            (xComponent as TRzCustomEdit).Text := xMainNode.AttributeByName[xComponent.Name];
        end;
        if xComponent is TRzCheckBox then
        begin
            (xComponent as TRzCheckBox).Checked := xml_X2Boolean(xMainNode.AttributeByName[xComponent.Name], false);
        end;
    end;
finally
    FreeAndNil(xDocument);
end;
 end;

   procedure TfrmFTPSetup.SaveToXML(szFileName : string);
var
xComponent : TComponent;
nLoop : Integer;
xMainNode : TXmlNode;
xDocument : TNativeXml;
begin
inherited;

xDocument := TNativeXml.CreateName('ftpcontrol');
try
    xMainNode := xml_ChildNodeByNameCreate(xDocument.Root, 'options');
    for nLoop := 0 to ComponentCount - 1 do
    begin
        xComponent := Components[nLoop];
        if xComponent is TRzCustomEdit then
        begin
            xMainNode.AttributeByName[xComponent.Name] := (xComponent as TRzCustomEdit).Text;
        end;
        if xComponent is TRzCheckBox then
        begin
            xMainNode.AttributeByName[xComponent.Name] := xml_Boolean2X((xComponent as TRzCheckBox).Checked);
        end;
    end;

    xDocument.XmlFormat := xfReadable;
    xDocument.SaveToFile(szFileName);
finally
    FreeAndNil(xDocument);
end;
 end;

L’accès aux propriétés des composants visuels d’une fiche n’est pas une bonne pratique. Il est considéré préférable d'avoir des propriétés séparées. Dans l'exemple ci-dessus, vous avez les propriétés nom d'utilisateur et mot de passe avec les méthodes get et set.

Par exemple:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
  private
    function GetPassword: string;
    function GetUsername: string;
    procedure SetPassword(const Value: string);
    procedure SetUsername(const Value: string);
  public
    property Password: string read GetPassword write SetPassword;
    property Username: string read GetUsername write SetUsername;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.GetPassword: string;
begin
 Result := Edit2.Text;
end;

function TForm1.GetUsername: string;
begin
 Result := Edit1.Text;
end;

procedure TForm1.SetPassword(const Value: string);
begin
  Edit2.Text := Value;
end;

procedure TForm1.SetUsername(const Value: string);
begin
  Edit1.Text := Value;
end;

end.

Cela signifie que vous pouvez modifier les composants visuels de la fiche sans que cela affecte le code d'appel.

Une autre option serait de transmettre l'objet en tant que propriété à la boîte de dialogue.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TUserObject = class(TObject)
  private
   FPassword: string;
   FUsername: string;
  public
   property Password: string read FPassword write FPassword;
   property Username: string read FUsername write FUsername;
  end;

  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    btnOK: TButton;
    procedure btnOKClick(Sender: TObject);
  private
    FUserObject: TUserObject;
    procedure SetUserObject(const Value: Integer);
  public
    property UserObject: Integer read FUserObject write SetUserObject;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnOKClick(Sender: TObject);
begin
 FUserObject.Username := Edit1.Text;
 FUserObject.Password := Edit2.Text;
 ModalResult := mrOK;
end;

procedure TForm1.SetUserObject(const Value: Integer);
begin
 FUserObject := Value;
 Edit1.Text := FUserObject.Username;
 Edit2.Text := FUserObject.Password;
end;

end.

L’espoir que cela aide.

Delphi a au moins un 'Avec', bien que cela ne résolve pas complètement le problème.

if (Dialog.ShowModal = mrOk) 
begin
  with MyObject do
  begin
    Username := Dialog.Edit1.Text;
    Password := Dialog.Edit2.Text;
    // ... again, many more of the same
  end;
end;

Et AFAIK, le constructeur, n’a rien à voir.

La liaison des contrôles aux données fonctionne bien dans Delphi, mais malheureusement uniquement lorsque ces données résident dans un descendant de TDataSet. Vous pourriez écrire un descendant de TDataSet qui utilise un objet pour le stockage de données, et il s'avère qu'une telle chose existe déjà. Voir le lien ci-dessous ... Cette implémentation semble fonctionner uniquement avec des collections d'objets (TCollection ou TObjectList), pas avec des objets isolés.

http://www.torry.net/pages.php?id=563 : recherchez dans la page "Snap Object DataSet"

.

Je n'ai pas d'expérience personnelle avec cela, mais ce serait très utile si cela fonctionnait et surtout s'il fonctionnerait également avec des instances d'objet unique, telles qu'une propriété sur un module de données ...

Recherchez le modèle de médiateur " ;. C'est un modèle de conception GoF, et dans leur livre, le GoF motive en fait ce modèle de conception dans une situation quelque peu similaire à celle que vous décrivez ici. Il vise à résoudre un problème différent - le couplage - mais je pense que vous avez également ce problème de toute façon.

En bref, l’idée est de créer un médiateur de dialogue, un objet supplémentaire placé entre tous les widgets de dialogue. Aucun widget ne connaît aucun autre widget, mais chaque widget connaît le médiateur. Le médiateur connaît tous les widgets. Lorsqu'un widget change, il en informe le médiateur. le médiateur en informe ensuite les widgets pertinents. Par exemple, lorsque vous cliquez sur OK, le médiateur peut informer d’autres widgets de cet événement.

Ainsi, chaque widget gère uniquement les événements et les actions qui le concernent. Le médiateur prend en charge l’interaction entre tous les widgets, c’est-à-dire que tout cela "passe-partout". le code est divisé sur tous les widgets, et le "résidu" Ce qui est global pour tous les widgets, c’est l’interaction, et c’est la responsabilité du médiateur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top