在delphi组件中发布属性类

时间:2015-08-29 21:34:03

标签: delphi

我在创建查找组件时遇到问题。

我会再试一次......把图像放在一边......

不保存dfm中的属性值...所以为什么,我的属性被分组在一个类中...如果它们是“松散的”将执行setter方法......

我怀疑是......为什么不跑?

我感谢你......

我的属性类

TLookupProperties = class(TPersistent)
private
  FDataCharCase: TEditCharCase;
  FOnLookupBeforeSearch: TNotifyEvent;
  FDataSource: TDataSource;
  FOnButtonClick: TNotifyEvent;
  FDataTabela: string;
  FOnExit: TNotifyEvent;
  FDataCondicao: string;
  FDataFieldDescricao: string;
  FDataFieldCodigo: string;
  FOnLookupValidate: TNotifyEvent;
  FDataFieldID: String;
published
  property OnLookupBeforeSearch: TNotifyEvent read FOnLookupBeforeSearch write FOnLookupBeforeSearch;
  property OnLookupExit: TNotifyEvent read FOnExit write FOnExit;
  property OnLookupButtonClick: TNotifyEvent read FOnButtonClick write FOnButtonClick;
  property OnLookupValidate: TNotifyEvent read FOnLookupValidate write FOnLookupValidate;

  property DataSource: TDataSource read FDataSource write FDataSource;
  property DataFieldID: String read FDataFieldID write FDataFieldID;
  property DataFieldCodigo: string read FDataFieldCodigo write FDataFieldCodigo;
  property DataFieldDescricao: string read FDataFieldDescricao write FDataFieldDescricao;
  property Condicao: string read FDataCondicao write FDataCondicao;
  property Tabela: string read FDataTabela write FDataTabela;
  property CharCase: TEditCharCase read FDataCharCase write FDataCharCase;
end;

我的组件

TDBLookupFrame = class(TFrame)
  PnlTotal: TPanel;
  btnButton: TSpeedButton;
  edtCodigo: TDBEdit;
  lblDescricao: TDBText;
  procedure edtCodigoExit(Sender: TObject);
  procedure btnButtonClick(Sender: TObject);
  procedure edtCodigoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  procedure edtCodigoKeyPress(Sender: TObject; var Key: Char);
strict private
  procedure SetarResult(AZerar: Boolean = False);
  procedure Validar(Sender: TObject);
private
  FLookupView: TLookupView;
  FLookupProperties: TLookupProperties;
  procedure SetLookupProperties(const Value: TLookupProperties);
public
  constructor Create(AOwner: TComponent); override;
  destructor Destroy; override;
published
  property LookupProperties: TLookupProperties read FLookupProperties write SetLookupProperties;
end;

procedure register;

implementation

uses System.SysUtils;

{$R *.dfm}

procedure register;
begin
  RegisterComponents('Hebran',[TDBLookupFrame]);
end;

procedure TDBLookupFrame.SetLookupProperties(const Value:   TLookupProperties);
begin
  FLookupProperties := Value;
  edtCodigo.CharCase := FLookupProperties.CharCase;
  FLookupView.Tabela := FLookupProperties.Tabela;
  FLookupView.CondicaoAdicional := FLookupProperties.Condicao;
  if Assigned(FLookupProperties.DataSource) then
  begin
    edtCodigo.DataSource := FLookupProperties.DataSource;
    lblDescricao.DataSource := FLookupProperties.DataSource;
    FLookupProperties.DataFieldDescricao :=      FLookupProperties.DataFieldCodigo;
   lblDescricao.DataField := FLookupProperties.DataFieldDescricao;
  end;
end;

constructor TDBLookupFrame.Create(AOwner: TComponent);
begin
  inherited;
  FLookupView := TLookupView.Create(Nil);
  FLookupProperties := TLookupProperties.Create;
  LookupProperties.Condicao := '';
  LookupProperties.CharCase := ecNormal; 
end;

3 个答案:

答案 0 :(得分:2)

查看此处(将DFM流式传输到组件时调用):

procedure TDBLookupFrame.SetLookupProperties(const Value:   TLookupProperties);
begin
  FLookupProperties := Value;
  edtCodigo.CharCase := FLookupProperties.CharCase;
  FLookupView.Tabela := FLookupProperties.Tabela;
  FLookupView.CondicaoAdicional := FLookupProperties.Condicao;
  if Assigned(FLookupProperties.DataSource) then
  begin
    edtCodigo.DataSource := FLookupProperties.DataSource;
    lblDescricao.DataSource := FLookupProperties.DataSource;
    FLookupProperties.DataFieldDescricao :=      FLookupProperties.DataFieldCodigo;
   lblDescricao.DataField := FLookupProperties.DataFieldDescricao;
  end;
end;

您正在致电

FLookupProperties := Value;

的确,当依靠IDE为您自动完成此操作时,它也会添加此功能。但是,根据您的情况,您不应该指定指针 - 因为您现在正在引用TLookupProperties的原始实例并将指针替换为您的副本。这也会泄漏内存,您已经在构造函数中创建了FLookupProperties,但由于您已经替换了指针,因此无法再引用该实例。

你应该改为呼叫

FLookupProperties.Assign(Value);

这将确保您创建原始值的完整副本,而不是仅仅引用实例(在该点之后可能会或可能不会自由)。

您的TLookupProperties也应该覆盖TPersistent.Assign,以便您可以将数据从一个实例复制到另一个实例。同样,对于任何类型的其他TPersistent属性,请勿使用:=因为它只是复制指针。相反,也可以在它们上使用.Assign

答案 1 :(得分:2)

尝试更像这样的东西:

interface

uses
  Classes, Forms, ...;

type
  TDBLookupFrame = class;

  TLookupProperties = class(TPersistent)
  private
    FOwner: TDBLookupFrame;
    FDataCharCase: TEditCharCase;
    FDataSource: TDataSource;
    FDataTabela: string;
    FDataCondicao: string;
    FDataFieldDescricao: string;
    FDataFieldCodigo: string;
    FDataFieldID: String;
    FOnChange: TNotifyEvent;
    FOnButtonClick: TNotifyEvent;
    FOnExit: TNotifyEvent;
    FOnLookupBeforeSearch: TNotifyEvent;
    FOnLookupValidate: TNotifyEvent;
    procedure Changed;
    procedure SetDataSource(const: Value: TDataSource);
    procedure SetDataFieldID(const Value: String);
    procedure SetDataFieldCodigo(const Value: string);
    procedure SetDataFieldDescricao(const Valu: string);
    procedure SetCondicao(const Value: string);
    procedure SetTabela(const Value: string);
    procedure SetCharCase(const Value: TEditCharCase);
  public
    constructor Create(AOwner: TDBLookupFrame);
    procedure Assign(Source: TPeristent); override;
  published
    property DataSource: TDataSource read FDataSource write SetDataSource;
    property DataFieldID: String read FDataFieldID write SetDataFieldID;
    property DataFieldCodigo: string read FDataFieldCodigo write SetDataFieldCodigo;
    property DataFieldDescricao: string read FDataFieldDescricao write SetDataFieldDescricao;
    property Condicao: string read FDataCondicao write SetDataCondicao;
    property Tabela: string read FDataTabela write SetDataTabela;
    property CharCase: TEditCharCase read FDataCharCase write SetDataCharCase;

    property OnChange: TNotifyEvent read FOnChange write FOnChange;
    property OnLookupBeforeSearch: TNotifyEvent read FOnLookupBeforeSearch write FOnLookupBeforeSearch;
    property OnLookupExit: TNotifyEvent read FOnExit write FOnExit;
    property OnLookupButtonClick: TNotifyEvent read FOnButtonClick write FOnButtonClick;
    property OnLookupValidate: TNotifyEvent read FOnLookupValidate write FOnLookupValidate;
  end;

  TDBLookupFrame = class(TFrame)
    PnlTotal: TPanel;
    btnButton: TSpeedButton;
    edtCodigo: TDBEdit;
    lblDescricao: TDBText;
    procedure edtCodigoExit(Sender: TObject);
    procedure btnButtonClick(Sender: TObject);
    procedure edtCodigoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure edtCodigoKeyPress(Sender: TObject; var Key: Char);
  strict private
    procedure SetarResult(AZerar: Boolean = False);
    procedure Validar(Sender: TObject);
  private
    FLookupView: TLookupView;
    FLookupProperties: TLookupProperties;
    procedure LookupPropertiesChanged(Sender: TObject);
    procedure SetLookupProperties(const Value: TLookupProperties);
  protected
    procedure Loaded; override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property LookupProperties: TLookupProperties read FLookupProperties write SetLookupProperties;
  end;

procedure Register;

implementation

uses
  System.SysUtils;

{$R *.dfm}

constructor TLookupProperties.Create(AOwner: TDBLookupFrame);
begin
  inherited Create;
  FOwner := AOwner;
  FDataCondicao := '';
  FDataCharCase := ecNormal;
end;

procedure TLookupProperties.Changed;
begin
  if Assigned(FOnChange) then
    FOnChange(Self);
end;

procedure TLookupProperties.SetDataSource(const: Value: TDataSource);
begin
  if FDataSource <> Value then
  begin
    if FDataSource <> nil then
      FDataSource.RemoveFreeNotification(FOwner);
    FDataSource := Value;
    if FDataSource <> nil then
      FDataSource.FreeNotification(FOwner);
    Changed;
  end;
end;

procedure TLookupProperties.SetDataFieldID(const Value: String);
begin
  if FDataFieldID <> Value then
  begin
    FDataFieldID := Value;
    Changed;
  end;
end;

procedure TLookupProperties.SetDataFieldCodigo(const Value: string);
begin
  if FDataFieldCodigo <> Value then
  begin
    FDataFieldCodigo := Value;
    Changed;
  end;
end;

procedure TLookupProperties.SetDataFieldDescricao(const Valu: string);
begin
  if FDataFieldDescricao <> Value then
  begin
    FDataFieldDescricao := Value;
    Changed;
  end;
end;

procedure TLookupProperties.SetCondicao(const Value: string);
begin
  if FDataCondicao <> Value then
  begin
    FDataCondicao := Value;
    Changed;
  end;
end;

procedure TLookupProperties.SetTabela(const Value: string);
begin
  if FDataTabela <> Value then
  begin
    FDataTabela := Value;
    Changed;
  end;
end;

procedure TLookupProperties.SetCharCase(const Value: TEditCharCase);
begin
  if FDataCharCase <> Value then
  begin
    FDataCharCase := Value;
    Changed;
  end;
end;

procedure TLookupProperties.Assign(Source: TPeristent);
var
  Src: TLookupProperties;
begin
  if Source is TLookupProperties then
  begin
    Src := TLookupProperties(Source);
    FDataCharCase := Src.FDataCharCase;
    SetDataSource(Src.FDataSource);
    FDataTabela := Src.FDataTabela;
    FDataCondicao := Src.FDataCondicao;
    FDataFieldDescricao := Src.FDataFieldDescricao;
    FDataFieldCodigo := Src.FDataFieldCodigo;
    FDataFieldID := Src.FDataFieldID;
    Changed;
  end else
    inherited;
end;

constructor TDBLookupFrame.Create(AOwner: TComponent);
begin
  inherited;
  FLookupView := TLookupView.Create(nil);
  FLookupProperties := TLookupProperties.Create(Self);
end;

destructor TDBLookupFrame.Destroy;
begin
  FLookupView.Free;
  FLookupProperties.Free;
  inherited;
end;

procedure TDBLookupFrame.Loaded;
begin
  inherited;
  LookupPropertiesChanged(nil);
end;

procedure TDBLookupFrame.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (AComponent = FLookupProperties.FDataSource) and (Operation = opRemove) then
    FLookupProperties.FDataSource := nil;
end;

procedure TDBLookupFrame.LookupPropertiesChanged(Sender: TObject);
begin
  if (ComponentState * [csLoading, csReading]) <> [] then
    Exit;

  edtCodigo.CharCase := FLookupProperties.CharCase;
  FLookupView.Tabela := FLookupProperties.Tabela;
  FLookupView.CondicaoAdicional := FLookupProperties.Condicao;

  edtCodigo.DataSource := FLookupProperties.DataSource;
  lblDescricao.DataSource := FLookupProperties.DataSource;
  FLookupProperties.DataFieldDescricao := FLookupProperties.DataFieldCodigo;
  lblDescricao.DataField := FLookupProperties.DataFieldDescricao;
end;

procedure TDBLookupFrame.SetLookupProperties(const Value:   TLookupProperties);
begin
  if FLookupProperties <> Value then
    FLookupProperties.Assign(Value);
end;

procedure Register;
begin
  RegisterComponents('Hebran', [TDBLookupFrame]);
end;

答案 2 :(得分:0)

抱歉,我的例子很简单......问题是该类没有执行TProperties类的属性集,然后,不保存.dfm中的值以将dataSource和dataField属性直接放在我的组件上,它执行set并写入dfm,但是,当您使用我的组件打开表单时,找不到保存在dfm中的属性值...(错误Ex:未找到属性数据源)