【问题标题】:published property class in delphi componentdelphi组件中发布的属性类
【发布时间】:2015-08-29 21:34:03
【问题描述】:

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

我会再试一次...把图片方便...。

不保存 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;

【问题讨论】:

  • 这显然不是你的全部代码。请将其余代码添加到 q;不要指望读者猜测你遗漏的部分是什么。同时,-1。顺便说一句,我已经删除了不相关的“注册商”标签。
  • 感谢您添加更多代码。你也可以显示TDBLookupFrameSetLookupProperties 的构造函数吗?您也可以删除register,因为它与您的问题完全无关。
  • 感谢您的帮助...我已经习惯了这个板...我的英语很糟糕
  • SetLookupProperties 应该只是一个简单的单行 FLookupProperties.Assign(Value); 然后 TLookupProperties 应该覆盖 Assign 过程。不过,还不完全确定这是否是您的问题。
  • 它的实现方式,数值保存在dfm中,但是,使用组件时关闭Delphi ...重新打开错误..."读取DBLookupFrame.LookupProperties.DataSource时出错不存在”...看来我需要注册 LookupProperties ...一些东西...

标签: delphi


【解决方案1】:

看这里(在将 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

【讨论】:

  • 其实这并没有解决...对于我这里的测试没有改变...当我在TLookupProperties属性中进行值的分配时,它们保存在dfm中,而不是它们的值再次打开表单时无法加载
  • 您的问题与保存无关。确实,它保存得很好。您的问题是在加载它时调用SetLookupProperties。这仍然是您绝对必须做的事情,但是由于我看不到您是如何实现它的,我不确定为什么它仍然不起作用你。
  • 我将属性中的值添加为链接中的图像.. prntscr.com/8anbqv 然后当我关闭 Delphi 并从此错误再次打开时... prntscr.com/8anczn
  • LookupProperties 我的属性要注册...因为它没有更多的重新打开Delphi ...prntscr.com/8anfe2
  • 您是否仍在使用组件的旧编译版本?你试过清理和重建你的包吗?
【解决方案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;

【讨论】:

  • 谢谢你的帮助我的朋友......但我不明白一些事情......我无法访问 TLookupProperties.SetdataSource 中的 FOwner...... DoChange 在 TLookupProperties.Assign 中已更改,是正确的?;对不起我的无知......但我的知识仍然有限并且正在提高......
  • 我的错。我已经开始添加 FOwner 然后删除它并忘记了 SetDataSource() 仍在使用它。我现在把它加回来了。
  • 再次感谢朋友...在我的代码中添加了它的解决方案,但是现在,要在表单上添加我的组件,有一个附件违规...仍然没有弄清楚为什么...
【解决方案3】:

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

【讨论】:

  • 您需要通过编辑将其添加到您的问题中,而不是发布答案。这不是答案。
猜你喜欢
  • 2015-02-23
  • 2011-07-23
  • 2012-11-02
  • 1970-01-01
  • 2022-10-12
  • 2017-05-11
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多