具有布尔类型的可为空的数据集字段,如何在链接到此字段的NULL
控件后代中以未检查状态显示其TDBCheckBox
值。默认情况下,TDBCheckBox
将字段的NULL
值显示为灰色复选框:
但我需要在TDBCheckBox
控件后代中将其显示为未选中状态:
修改原始TDBCheckBox
源代码不是我的选择,也不能覆盖TDBCheckBox.GetFieldState
,因为它是私有方法。
因此,如何在NULL
后代中将TDBCheckBox
值显示为未经检查的状态?
最佳答案
如果您的项目是封闭源代码,建议您复制一份DBCtrls
,将其改为Result := cbGrayed
,并将其明确添加到项目中。更改将在您的整个应用程序中进行,但不会更改原始代码。
然而,还有另一种方式-实际上是一个黑客,所以要当心,我建议放置一个编译器指令,以防止将此指令编译到其他Delphi版本中,从而要求再次查看该代码并确保其有效。
这是在Delphi XE中可用的代码-在Delphi 6中看起来可能有所不同,但是您会明白的。
type
TDBCheckBoxHack = class(TCustomCheckBox)
private
FDataLink: TFieldDataLink;
FValueCheck: string;
FValueUncheck: string;
procedure DataChange(Sender: TObject);
function GetFieldState: TCheckBoxState;
function ValueMatch(const ValueList, Value: string): Boolean;
end;
我忽略了这些方法的实现,因为它们只是原始受版权保护的代码的副本。您必须在
GetFieldState
方法中更改一两行。诀窍是创建与原始TDBCheckBox相同的内存布局,以便您可以访问私有字段-这就是为什么应谨慎使用此代码的原因!
然后,将固定的
DataChange
方法分配给数据链接:TDBCheckBoxHack(DBCheckBox1).FDataLink.OnDataChange :=
TDBCheckBoxHack(DBCheckBox1).DataChange;
为了使它更易于使用,您可以使用从原始
TDBCheckBox
继承的另一种技巧,并完全相同地调用您的类。然后,您可以将其放入某个单元中,并在使用时将其添加到DBCtrls
之后。这将导致为您放置在窗体上的每个TDBCheckBox
调用构造函数,而无需使用自己的构造函数并将其注册到IDE:type
TDBCheckBox = class(DBCtrls.TDBCheckBox)
public
constructor Create(AOwner: TComponent); override;
end;
constructor TDBCheckBox.Create(AOwner: TComponent);
begin
inherited;
TDBCheckBoxHack(Self).FDataLink.OnDataChange := TDBCheckBoxHack(Self).DataChange;
end;