如何为Control Designer添加属性?自定义控件设计器动词与下拉菜单扩展疑问
嗨,我来帮你搞定这个自定义控件设计器的问题!我知道你已经会用DesignerVerbCollection添加基础设计器动词,但卡在了怎么绑定控件属性的动词,还有实现带下拉菜单的多级选项上——这俩需求我都帮你拆解清楚!
一、添加与控件属性关联的DesignerVerb
要实现像“编辑项...”“编辑列...”这种和控件属性绑定的动词,关键是在动词的回调逻辑里直接唤起对应属性的编辑器,和你在属性窗口里编辑该属性的体验完全一致。
给你举个实际的例子:假设你的自定义控件有一个ItemCollection类型的Items属性,要添加“Editar elementos...”(编辑项...)的动词,代码可以这么写:
public class MyCustomControlDesigner : ControlDesigner { private DesignerVerbCollection _verbs; public override DesignerVerbCollection Verbs { get { if (_verbs == null) { _verbs = new DesignerVerbCollection(); // 添加关联Items属性的编辑动词 _verbs.Add(new DesignerVerb("Editar elementos...", (sender, e) => { var targetControl = (MyCustomControl)Component; // 获取属性描述器,唤起内置的集合编辑器 var propDescriptor = TypeDescriptor.GetProperties(targetControl)["Items"]; var collectionEditor = propDescriptor.GetEditor(typeof(UITypeEditor)) as UITypeEditor; if (collectionEditor != null) { var editorService = GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService; collectionEditor.EditValue(editorService, targetControl, propDescriptor.GetValue(targetControl)); } })); // 同理添加关联Columns属性的"Editar columnas..."动词 _verbs.Add(new DesignerVerb("Editar columnas...", (sender, e) => { // 复制上面的逻辑,把"Items"替换成你的Columns属性名即可 })); } return _verbs; } } }
点击这个动词时,就会弹出和属性窗口里编辑Items属性一样的集合编辑器对话框,完全符合你的需求。
二、实现带下拉菜单的多级设计器选项
默认的DesignerVerb只能做单级菜单,要实现像“Vista”(视图)这种带下拉子项的效果,得用DesignerActionList——这是VS设计器用来做智能标签多级菜单的标准方式。
步骤1:自定义DesignerActionList类
先写一个包含下拉菜单逻辑的ActionList:
public class MyCustomControlActionList : DesignerActionList { private readonly MyCustomControl _control; private readonly DesignerActionUIService _uiService; public MyCustomControlActionList(MyCustomControl control) : base(control) { _control = control; _uiService = (DesignerActionUIService)GetService(typeof(DesignerActionUIService)); } public override DesignerActionItemCollection GetSortedActionItems() { var actionItems = new DesignerActionItemCollection(); // 添加分组标题(对应你的"Vista") actionItems.Add(new DesignerActionHeaderItem("Vista")); // 添加下拉子项(对应你的"ImageList pequeña"等选项) actionItems.Add(new DesignerActionMethodItem( this, nameof(SetSmallImageList), "ImageList pequeña", "Vista", "切换为小型ImageList")); actionItems.Add(new DesignerActionMethodItem( this, nameof(SetLargeImageList), "ImageList grande", "Vista", "切换为大型ImageList")); return actionItems; } // 子选项对应的执行逻辑 public void SetSmallImageList() { // 这里写切换到小型ImageList的逻辑,比如给控件的ImageList属性赋值 _control.ImageList = _control.SmallImageList; _uiService.Refresh(_control); } public void SetLargeImageList() { _control.ImageList = _control.LargeImageList; _uiService.Refresh(_control); } }
步骤2:在ControlDesigner里关联ActionList
回到你的MyCustomControlDesigner,添加ActionList的重写逻辑:
public class MyCustomControlDesigner : ControlDesigner { private DesignerActionListCollection _actionLists; // 保留之前的Verbs代码(处理单级编辑动词) private DesignerVerbCollection _verbs; public override DesignerVerbCollection Verbs { get { // 之前的代码不变 } } // 添加ActionList的重写 public override DesignerActionListCollection ActionLists { get { if (_actionLists == null) { _actionLists = new DesignerActionListCollection(); _actionLists.Add(new MyCustomControlActionList((MyCustomControl)Component)); } return _actionLists; } } }
这样在设计器里,你的控件右上角会出现一个小箭头(智能标签按钮),点击后就能看到“Vista”分组下的下拉子菜单,和你示意图里的效果完全一致。
三、适配西班牙语Visual Studio的小提示
因为你的VS是西班牙语版本,系统自带的设计器文本(比如编辑器对话框的标题)会自动适配,但你自定义的动词和菜单文本直接写西班牙语就行(比如"Editar elementos..."),VS会直接显示你定义的内容,不用额外做本地化处理。
内容的提问来源于stack exchange,提问作者user9264959

