【问题标题】:Make Non-Windowed Component Data Aware使非窗口组件数据感知
【发布时间】:2012-06-09 01:47:33
【问题描述】:

我有一个带有日期属性的非窗口组件。我想通过对日期字段的读取和写入功能使此组件数据感知。 (换句话说,如果我在运行时更改日期,我想将新的日期属性值写入数据集。)我已经搜索了示例,但我找不到任何示例。找到了几个只读示例,例如 TDbLabel,但没有一个允许将更改写入数据集。如果有人能给我举个例子,我将不胜感激。

【问题讨论】:

  • 如果日期控件不是窗口控件,您希望如何允许用户在运行时更改日期控件的值?
  • @Rob McDonell 如果用户是程序员(我,但不一定是熟练的程序员),则发布该属性。因此,我可以在程序中的任何位置设置它,就像任何其他已发布(或公共)属性一样。
  • 可以,但如果是程序员在控件上设置发布属性,程序员也可以直接更新数据集,这样就不需要数据感知控件了。

标签: database delphi components data-aware


【解决方案1】:

这是解决您问题的通用代码方法

unit Unit1;

interface

uses
   Classes
  ,DB
  ,DBCtrls
  ;
type
  TDataAwareComponent = class(TComponent)
  private
    { private declarations }
    FDataLink : TFieldDataLink;
    FFromDateChange : Boolean;
    function GetDataField: string;
    function GetDataSource: TDataSource;
    function GetField: TField;
    function GetReadOnly: Boolean;
    procedure SetDataField(const Value: string);
    procedure SetDataSource(const Value: TDataSource);
    procedure SetReadOnly(const Value: Boolean);
    function GetDateProperty: TDateTime;
    procedure SetDateProperty(const Value: TDateTime);
  protected
    { protected declarations }
    procedure DataChange(Sender : TObject);
  public
    { public declarations }
    constructor Create(AOwner : TComponent);override;
    destructor  Destroy;override;
  public
    property Field        : TField    read GetField;
    property DateProperty : TDateTime read GetDateProperty write SetDateProperty;
  published
    { published declarations }
   property DataSource   : TDataSource           read GetDataSource  write SetDataSource;
   property DataField    : string                read GetDataField   write SetDataField;
   property ReadOnly     : Boolean               read GetReadOnly    write SetReadOnly;
  end;

implementation

{ TDataAwareComponent }
{------------------------------------------------------------------------------}
constructor TDataAwareComponent.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FDataLink                 := TFieldDataLink.Create;
  FDataLink.Control         := Self;
  FDataLink.OnDataChange    := DataChange;
end;
{------------------------------------------------------------------------------}
destructor TDataAwareComponent.Destroy;
begin
  FDataLink.Free;
  FDataLink := nil;
  inherited;
end;
{------------------------------------------------------------------------------}
procedure TDataAwareComponent.DataChange(Sender: TObject);
begin
  // Here a visual object would display the underlying field value.
  // For example if this component was a TEdit
  // the code would be something like

{  if FDataLink.Active then
    Self.Text := Field.AsString;
    And on the exit event of the TEdit the code would be reversed
    so the field can take the value the user entered.

    Since you do not need any UI interaction propably this event
    is useless to you.
    }
    // Of course there are more issues you should cover to
    // have a complete working solution.
    // This is only demostration code.

end;
{------------------------------------------------------------------------------}
function TDataAwareComponent.GetDataField: string;
begin
  Result := FDataLink.FieldName
end;
{------------------------------------------------------------------------------}
function TDataAwareComponent.GetDataSource: TDataSource;
begin
  Result := FDataLink.DataSource;
end;
{------------------------------------------------------------------------------}
function TDataAwareComponent.GetDateProperty: TDateTime;
begin
  //You do not need a separate property since you can access directly the field value.
  Result := 0;
  if Assigned(Field) and (Field.DataType in [ftTime,ftDate,ftDateTime]   then
    Result := Field.AsDateTime;
end;
{------------------------------------------------------------------------------}
function TDataAwareComponent.GetField: TField;
begin
  Result : FDataLink.Field;
end;
{------------------------------------------------------------------------------}
function TDataAwareComponent.GetReadOnly: Boolean;
begin
  Result := FDataLink.ReadOnly;
end;
{------------------------------------------------------------------------------}
procedure TDataAwareComponent.SetDataField(const Value: string);
begin
  FDataLink.FieldName := Value;
end;
{------------------------------------------------------------------------------}
procedure TDataAwareComponent.SetDataSource(const Value: TDataSource);
begin
  FDataLink.DataSource := Value;
end;
{------------------------------------------------------------------------------}
procedure TDataAwareComponent.SetDateProperty(const Value: TDateTime);
begin
  if Assigned(Field)  then
  begin
    FFromDateChange := True;
    try
      Field.DataSet.Edit;
      Field.Value := Value;
    finally
      FFromDateChange := False;
    end;
  end;
end;
{------------------------------------------------------------------------------}
procedure TDataAwareComponent.SetReadOnly(const Value: Boolean);
begin
  FDataLink.ReadOnly := Value;
end;
{------------------------------------------------------------------------------}

end.

【讨论】:

  • 非常感谢。不知道为什么,但我对此有一个真正的心理障碍。另外,感谢您回答问题,而不是问为什么我会这么愚蠢地问它。
【解决方案2】:

这将是一些代码,但是如果您的组件在其值更改时触发了事件,那么如果它处于 dsEdit 状态,则可以使用它来将更新的值发送到数据集。您还需要处理各种TDataSource Events 以了解数据集何时发生变化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-12
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    相关资源
    最近更新 更多