У меня есть неоконный компонент со свойством даты. Я хотел бы, чтобы данные этого компонента были осведомлены о возможностях чтения и записи в поле даты. (Другими словами, если я изменю дату во время выполнения, я хотел бы записать новое значение свойства даты в набор данных.) Я гуглил примеры, но не смог их найти. Обнаружено несколько примеров только для чтения, например TDbLabel, но ни один из них не позволяет записывать изменения в набор данных. Если кто-то может указать мне на пример, я был бы признателен.
Обеспечьте осведомленность о данных не оконных компонентов
comment
Как вы предполагаете разрешить пользователю изменять значение элемента управления датой во время выполнения, если это НЕ оконный элемент управления?
- person Rob McDonell   schedule 05.06.2012
comment
@Rob McDonell Если пользователь является программистом (я, но не обязательно опытный программист), свойство публикуется. Таким образом, я могу установить его в любом месте своей программы, как и любое другое опубликованное (или общедоступное) свойство.
- person Max Williams   schedule 05.06.2012
comment
Да, но если это программист, устанавливающий опубликованное свойство в элементе управления, программист также может напрямую обновить набор данных, поэтому нет необходимости в элементе управления с поддержкой данных.
- person Rob McDonell   schedule 05.06.2012
Ответы (2)
Вот общий кодовый подход к вашему вопросу
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.
person
George Trifidis
schedule
05.06.2012
Большое спасибо. Не знаю почему, но у меня был настоящий ментальный блок по этому поводу. Кроме того, спасибо за ответ на вопрос, а не за вопрос, почему я был бы настолько глуп, чтобы задать его.
- person Max Williams; 05.06.2012
Это было бы немного кода, но если ваш компонент имеет события, запускаемые при изменении его значения, то это можно использовать для отправки обновленных значений в набор данных, если он находится в состоянии dsEdit
. Вам также потребуется обрабатывать различные события TDataSource, чтобы знать когда набор данных меняется.
person
afrazier
schedule
05.06.2012