如何让 TDBCheckBox 在点击后立即更新它的 DataField?
How to make TDBCheckBox update its DataField immediately after click?
我有一个包含多个控件的表单,其中第一个是绑定到 DataField := 'enabled'
的 TDBCheckBox
。
单击复选框后,我希望启用/禁用所有剩余控件。
procedure TMyAdapter.DataSourceDataChange(Sender: TObject; Field: TField);
var
Enabled: Boolean;
begin
Enabled := FModel.DataSet['enabled'].AsBoolean;
FView.Label1.Enabled := Enabled;
FView.DBEdit1.Enabled := Enabled;
FView.Label2.Enabled := Enabled;
FView.DBEdit2.Enabled := Enabled;
FView.Label3.Enabled := Enabled;
FView.DBEdit3.Enabled := Enabled;
FView.Label4.Enabled := Enabled;
FView.DBEdit4.Enabled := Enabled;
end;
这仅在焦点离开复选框或滚动数据集时有效(我在此表单上也有导航器)。
有没有办法让复选框立即更新其数据字段?
或者是否有更好的替代方法来实现我所描述的?
您可以调用 DataSets UpdateRecord
方法使任何链接的 DB 控件将其数据存储到基础字段中。
使用 DataChange 事件做这样的事情有几个问题
它被调用的频率比您实际需要的要高得多,以响应您的 DBCheckBox 被点击和
对数据集执行 .Post 会改变其状态,这在事件中通常是个坏主意,事件本身可能由数据集状态的变化触发。
我,最好使用一种标准化的方法来处理这类问题,我使用的方法是编写一个自定义消息处理程序来完成您想要的工作,并使用 Post 调用它来自您的 DBCheckBox1Click 处理程序的消息,如下所示:
const
WM_AutoPost = WM_User + 1;
type
TForm1 = class(TForm)
[...]
private
procedure DoAutoPost;
procedure WMAutoPost(var Msg : TMessage); message WM_Autopost;
[...]
end;
var
Form1: TForm1;
implementation
[...]
procedure TForm1.DBCheckBox1Click(Sender: TObject);
begin
PostMessage(Self.Handle, WM_AutoPost, 0, 0);
end;
procedure TForm1.DoAutoPost;
begin
if CDS1.State in [dsEdit, dsInsert] then begin
CDS1.Post;
// Update other controls here
end;
end;
procedure TForm1.WMAutoPost(var Msg: TMessage);
begin
DoAutoPost;
end;
这是我根据 Uwe 和 MartynA 的答案构建的解决方案:
procedure TMyAdapter.EnabledClick(Sender: TObject);
begin
PostMessage(FView.Handle, WM_ENABLED_CLICKED, 0, 0);
end;
procedure TMyAdapter.WMEnabledClicked(var Msg: TMessage);
var
DataSet: TDataSet;
begin
DataSet := FView.EnabledCheckBox.Field.DataSet;
if not (DataSet.State in [dsInsert, dsEdit]) then
DataSet.Edit;
DataSet.UpdateRecord;
end;
procedure TMyAdapter.DataSourceDataChange(Sender: TObject; Field: TField);
var
Enabled: Boolean;
begin
if (Field = nil) or (Field = FView.EnabledCheckBox.Field) then
begin
Enabled := FView.EnabledCheckBox.Field.AsBoolean;
FView.Label1.Enabled := Enabled;
FView.DBEdit1.Enabled := Enabled;
// etc.
end;
end;
我有一个包含多个控件的表单,其中第一个是绑定到 DataField := 'enabled'
的 TDBCheckBox
。
单击复选框后,我希望启用/禁用所有剩余控件。
procedure TMyAdapter.DataSourceDataChange(Sender: TObject; Field: TField);
var
Enabled: Boolean;
begin
Enabled := FModel.DataSet['enabled'].AsBoolean;
FView.Label1.Enabled := Enabled;
FView.DBEdit1.Enabled := Enabled;
FView.Label2.Enabled := Enabled;
FView.DBEdit2.Enabled := Enabled;
FView.Label3.Enabled := Enabled;
FView.DBEdit3.Enabled := Enabled;
FView.Label4.Enabled := Enabled;
FView.DBEdit4.Enabled := Enabled;
end;
这仅在焦点离开复选框或滚动数据集时有效(我在此表单上也有导航器)。
有没有办法让复选框立即更新其数据字段?
或者是否有更好的替代方法来实现我所描述的?
您可以调用 DataSets UpdateRecord
方法使任何链接的 DB 控件将其数据存储到基础字段中。
使用 DataChange 事件做这样的事情有几个问题
它被调用的频率比您实际需要的要高得多,以响应您的 DBCheckBox 被点击和
对数据集执行 .Post 会改变其状态,这在事件中通常是个坏主意,事件本身可能由数据集状态的变化触发。
我,最好使用一种标准化的方法来处理这类问题,我使用的方法是编写一个自定义消息处理程序来完成您想要的工作,并使用 Post 调用它来自您的 DBCheckBox1Click 处理程序的消息,如下所示:
const
WM_AutoPost = WM_User + 1;
type
TForm1 = class(TForm)
[...]
private
procedure DoAutoPost;
procedure WMAutoPost(var Msg : TMessage); message WM_Autopost;
[...]
end;
var
Form1: TForm1;
implementation
[...]
procedure TForm1.DBCheckBox1Click(Sender: TObject);
begin
PostMessage(Self.Handle, WM_AutoPost, 0, 0);
end;
procedure TForm1.DoAutoPost;
begin
if CDS1.State in [dsEdit, dsInsert] then begin
CDS1.Post;
// Update other controls here
end;
end;
procedure TForm1.WMAutoPost(var Msg: TMessage);
begin
DoAutoPost;
end;
这是我根据 Uwe 和 MartynA 的答案构建的解决方案:
procedure TMyAdapter.EnabledClick(Sender: TObject);
begin
PostMessage(FView.Handle, WM_ENABLED_CLICKED, 0, 0);
end;
procedure TMyAdapter.WMEnabledClicked(var Msg: TMessage);
var
DataSet: TDataSet;
begin
DataSet := FView.EnabledCheckBox.Field.DataSet;
if not (DataSet.State in [dsInsert, dsEdit]) then
DataSet.Edit;
DataSet.UpdateRecord;
end;
procedure TMyAdapter.DataSourceDataChange(Sender: TObject; Field: TField);
var
Enabled: Boolean;
begin
if (Field = nil) or (Field = FView.EnabledCheckBox.Field) then
begin
Enabled := FView.EnabledCheckBox.Field.AsBoolean;
FView.Label1.Enabled := Enabled;
FView.DBEdit1.Enabled := Enabled;
// etc.
end;
end;