c# - 从工具箱拖放自定义控件时生成代码或事件
问题描述
我正在创建一个自定义控件(例如自定义 LookUpEdit),我想知道当我将这个控件拖放到里面时,我是否可以自动生成代码(例如 form.cs 文件中的 EditValueChanged 事件或一些代码行,例如 Form_Load 事件中)表单设计器,让任何开发人员都有机会轻松查看和扩展此代码(如果他/她愿意)。
我的问题是:在设计时从工具箱中拖放自定义控件时,如何在表单(form.cs)中自动生成代码或事件?
解决方案
有时您可能希望在表单上放置组件时生成一些代码。例如,当您将数据源从数据源窗口拖放到表单上时,您会看到类似的行为。
这种行为对于扩展和加载项更为常见,但您也可以在从工具箱中删除组件时为您的组件实现此类行为。
答案的关键点是:
- 通过派生为控件创建新设计器
ControlDesigner
- 使用创建事件处理程序
IEventBindingService
- 使用服务将代码添加到事件处理程序的主体
CodeTypeDeclaration
。
例子
我MyControl
在这个例子中创建了一个控件。当您将控件的实例拖放到窗体上时,设计器将为其Click
事件生成以下代码:
private void myControl1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hi!");
}
这是 和 的MyControl
代码MyControlDesigner
。您可能希望在代码中添加空值检查。
using System.CodeDom;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Forms.Design;
[Designer(typeof(MyControlDesigner))]
public partial class MyControl : Control
{
}
public class MyControlDesigner : ControlDesigner
{
public override void InitializeNewComponent(IDictionary defaultValues)
{
base.InitializeNewComponent(defaultValues);
var component = this.Component;
var eventBindingService = (IEventBindingService)this.GetService(
typeof(IEventBindingService));
var componentChangeService = (IComponentChangeService)this.GetService(
typeof(IComponentChangeService));
var designerHostService = (IDesignerHost)GetService(typeof(IDesignerHost));
var uiService = (IUIService)GetService(typeof(IUIService));
var designerTransaction = (DesignerTransaction)null;
try
{
designerTransaction = designerHostService.CreateTransaction();
var e = TypeDescriptor.GetEvents(component)["Click"];
if (e != null)
{
var methodName = eventBindingService.CreateUniqueMethodName(component, e);
var eventProperty = eventBindingService.GetEventProperty(e);
if (eventProperty.GetValue(component) == null)
{
eventProperty.SetValue(component, methodName);
var code = this.GetService(typeof(CodeTypeDeclaration))
as CodeTypeDeclaration;
CodeMemberMethod method = null;
var member = code.Members.Cast<CodeTypeMember>()
.Where(x => x.Name == methodName).FirstOrDefault();
if (member != null)
{
method = (CodeMemberMethod)member;
method.Statements.Add(
new CodeSnippetStatement("MessageBox.Show(\"Hi!\");"));
}
componentChangeService.OnComponentChanged(component,
eventProperty, null, null);
eventBindingService.ShowCode(component, e);
}
}
designerTransaction.Commit();
}
catch (System.Exception ex)
{
if (designerTransaction != null)
designerTransaction.Cancel();
uiService.ShowError(ex);
}
}
}
推荐阅读
- android - 在android(Kotlin)中单击时如何引用按钮视图?
- node.js - NPM/PM2 - 找不到命令
- regex - 重定向除 .htaccess 中的一个以外的所有 url
- php - 用户无法在已发布的网站上上传图片
- reactjs - 将 MaterialUI 伪类选择器与 makeStyles 一起使用
- mysql - MYSQL:更新前触发器不适用于所有查询
- python - 在 Python 中调用函数到新函数
- angular - 质朴是什么意思?
- python - 当我使用 python manage.py runserver 进入 django admin 时,发生'ValueError at /admin'
- selenium - 如何识别动态图像的元素