简体   繁体   English

使非窗口组件数据感知

[英]Make Non-Windowed Component Data Aware

I have a non-windowed component with a date property. 我有一个带有date属性的非窗口组件。 I would like to make this component data aware with read and write capabilities to a date field. 我想通过对日期字段的读写功能使该组件数据具有感知性。 (In other words, if I change the date at runtime, I would like to write the new date property value to the dataset.) I have googled for examples, but I haven't been able to find any. (换句话说,如果我在运行时更改日期,我想将新的date属性值写入数据集。)我已经搜索了一些示例,但找不到任何示例。 Found several read-only examples, eg, TDbLabel, but none that allow changes to be written to the dataset. 找到了几个只读示例,例如TDbLabel,但没有一个示例允许将更改写入数据集。 If anyone can point me to an example, I would be grateful. 如果有人能给我指出一个例子,我将不胜感激。

Here is a generic code approach to your question 这是解决您问题的通用代码方法

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.

It'd be a bit of code, but if your component has events triggered when its value changes, then that could be used to send updated values to the dataset, if it's in the dsEdit state. 这将是一些代码,但是如果您的组件的值发生更改时触发了事件,则可以将更新后的值发送到数据集(如果它处于dsEdit状态)。 You'd also need to handle the various TDataSource Events to know when the dataset is changing. 您还需要处理各种TDataSource事件,以了解数据集何时更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM