如何调整自定义Delphi组件TBtnsHints类的属性显示顺序
Delphi自定义组件:TBtnsHints属性排序的优雅解决方案
我在开发带颜色的自定义BindNavigator组件时,遇到TBtnsHints子属性排序的问题。目前通过给published属性加_n前缀来控制显示顺序(First、Prior……CancelUpdate),但这种方式不够优雅,有没有更好的实现方法?当前代码如下:
TBtnsHints = class (TPersistent) private FOwner : TColoredBindNavigator; FButtonHints : TButtonHints; function GetHint(const index : Integer) : String; function HintisStored(const index: Integer) : Boolean; procedure SetHint(const index : Integer; const Value : String) ; public constructor Create(aOwner : TColoredBindNavigator); destructor Destroy; override; published property _1First : String index 0 read GetHint write SetHint stored HintisStored; property _2Prior : String index 1 read GetHint write SetHint stored HintisStored; property _3Next : String index 2 read GetHint write SetHint stored HintisStored; property _4Last : String index 3 read GetHint write SetHint stored HintisStored; property _5Insert : String index 4 read GetHint write SetHint stored HintisStored; property _6Delete : String index 5 read GetHint write SetHint stored HintisStored; property _7Edit : String index 6 read GetHint write SetHint stored HintisStored; property _8Post : String index 7 read GetHint write SetHint stored HintisStored; property _9Cancel : String index 8 read GetHint write SetHint stored HintisStored; property __0Refresh : String index 9 read GetHint write SetHint stored HintisStored; property __1ApplyUpdate : String index 10 read GetHint write SetHint stored HintisStored; property __2CancelUpdate : String index 11 read GetHint write SetHint stored HintisStored; end;
方案1:使用[Order]属性修饰符(Delphi XE及以上版本)
从Delphi XE开始,官方提供了[Order(N)]元数据标签,可以直接指定设计器中属性的显示顺序,N值越小,属性越靠前。这种方法无需额外代码,是最简洁的解决方案:
TBtnsHints = class (TPersistent) private FOwner : TColoredBindNavigator; FButtonHints : TButtonHints; function GetHint(const index : Integer) : String; function HintisStored(const index: Integer) : Boolean; procedure SetHint(const index : Integer; const Value : String) ; public constructor Create(aOwner : TColoredBindNavigator); destructor Destroy; override; published [Order(0)] property First : String index 0 read GetHint write SetHint stored HintisStored; [Order(1)] property Prior : String index 1 read GetHint write SetHint stored HintisStored; [Order(2)] property Next : String index 2 read GetHint write SetHint stored HintisStored; [Order(3)] property Last : String index 3 read GetHint write SetHint stored HintisStored; [Order(4)] property Insert : String index 4 read GetHint write SetHint stored HintisStored; [Order(5)] property Delete : String index 5 read GetHint write SetHint stored HintisStored; [Order(6)] property Edit : String index 6 read GetHint write SetHint stored HintisStored; [Order(7)] property Post : String index 7 read GetHint write SetHint stored HintisStored; [Order(8)] property Cancel : String index 8 read GetHint write SetHint stored HintisStored; [Order(9)] property Refresh : String index 9 read GetHint write SetHint stored HintisStored; [Order(10)] property ApplyUpdate : String index 10 read GetHint write SetHint stored HintisStored; [Order(11)] property CancelUpdate : String index 11 read GetHint write SetHint stored HintisStored; end;
方案2:自定义属性编辑器(兼容旧版Delphi)
如果需要支持Delphi XE之前的版本,可通过编写自定义属性编辑器来强制控制属性显示顺序:
第一步:注册自定义属性编辑器
在组件的注册单元中添加以下代码:
uses DesignEditors, DesignIntf; type TBtnsHintsEditor = class(TPropertyEditor) public function GetAttributes: TPropertyAttributes; override; procedure GetProperties(Proc: TGetPropProc); override; end; procedure Register; begin RegisterPropertyEditor(TypeInfo(TBtnsHints), nil, '', TBtnsHintsEditor); end; { TBtnsHintsEditor } function TBtnsHintsEditor.GetAttributes: TPropertyAttributes; begin Result := [paSubProperties]; end; procedure TBtnsHintsEditor.GetProperties(Proc: TGetPropProc); const PropOrder: array[0..11] of string = ( 'First', 'Prior', 'Next', 'Last', 'Insert', 'Delete', 'Edit', 'Post', 'Cancel', 'Refresh', 'ApplyUpdate', 'CancelUpdate' ); var I: Integer; PropInfo: PPropInfo; begin // 按自定义顺序遍历属性,传递给设计器显示 for I := Low(PropOrder) to High(PropOrder) do begin PropInfo := GetPropInfo(GetComponent(0), PropOrder[I]); if Assigned(PropInfo) then Proc(PropInfo); end; end;
第二步:清理TBtnsHints的属性名
去掉属性名前缀,恢复正常命名:
TBtnsHints = class (TPersistent) private FOwner : TColoredBindNavigator; FButtonHints : TButtonHints; function GetHint(const index : Integer) : String; function HintisStored(const index: Integer) : Boolean; procedure SetHint(const index : Integer; const Value : String) ; public constructor Create(aOwner : TColoredBindNavigator); destructor Destroy; override; published property First : String index 0 read GetHint write SetHint stored HintisStored; property Prior : String index 1 read GetHint write SetHint stored HintisStored; property Next : String index 2 read GetHint write SetHint stored HintisStored; property Last : String index 3 read GetHint write SetHint stored HintisStored; property Insert : String index 4 read GetHint write SetHint stored HintisStored; property Delete : String index 5 read GetHint write SetHint stored HintisStored; property Edit : String index 6 read GetHint write SetHint stored HintisStored; property Post : String index 7 read GetHint write SetHint stored HintisStored; property Cancel : String index 8 read GetHint write SetHint stored HintisStored; property Refresh : String index 9 read GetHint write SetHint stored HintisStored; property ApplyUpdate : String index 10 read GetHint write SetHint stored HintisStored; property CancelUpdate : String index 11 read GetHint write SetHint stored HintisStored; end;
方案3:数组属性替代独立属性(可选)
如果允许调整属性访问方式,可将所有提示封装为数组属性,设计器会按索引顺序显示,同时可保留命名属性作为快捷访问:
TBtnsHints = class (TPersistent) private FOwner : TColoredBindNavigator; FButtonHints : TButtonHints; function GetHint(const index : Integer) : String; function HintisStored(const index: Integer) : Boolean; procedure SetHint(const index : Integer; const Value : String) ; public constructor Create(aOwner : TColoredBindNavigator); destructor Destroy; override; published property Hints[Index: Integer]: String read GetHint write SetHint stored HintisStored; default; // 保留命名属性方便直接访问 property First : String index 0 read GetHint write SetHint stored HintisStored; property Prior : String index 1 read GetHint write SetHint stored HintisStored; // ... 其余属性同上 end;
内容的提问来源于stack exchange,提问作者SergeGirard
相关产品推荐
相关产品推荐

