通常,当您从工具箱中删除控件时想要分配属性时,您不需要手动生成代码,例如您可以轻松地做到这一点:
public MyUserControl()
{
InitializeComponent();
MyTextProperty = "Something";
}
并且会自动序列化。
但是对于更高级的要求,还有更多选项。如果您知道自己拥有的选项,则可以根据自己的要求进行选择。以下是一些选项:
- 在构造函数或属性中分配一些值
- 使用
ToolboxItem为属性赋值,它会覆盖你在构造函数中赋值的值。
- 为表单的
Load 事件生成一些代码并在那里初始化属性。它对于复杂的代码生成很有用,例如,当您删除数据源时,它会生成一些代码来加载数据并添加到表单的加载事件。
假设您在构造函数中将Something 分配给MyTextProperty,那么当您将控件放到表单中时,designer.cs 中将生成以下内容:
this.myUserControl1.MyTextProperty = "Something";
如果您使用ToolboxItem 解决方案将Something else 分配给属性,designer.cs 文件中的结果将是:
this.myUserControl1.MyTextProperty = "Something else";
如果您决定使用第三个选项并生成事件处理程序代码,designer.cs 文件中的结果将是:
this.Load += new System.EventHandler(this.Form1_Load);
cs 文件中的结果将是:
private void Form1_Load(object sender, EventArgs e)
{
myUserControl1.MyTextProperty = "Even something else!";
}
示例
这里是MyUserControl、MyUserControlToolboxItem和MyUserControlDesigner的完整代码。您可以评论Designer 和/或ToolboxItem 属性并关闭所有设计器并清理和重建解决方案并将控件实例拖放到表单上以查看其工作原理。
using System.CodeDom;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Forms.Design;
[Designer(typeof(MyUserControlDesigner))]
[ToolboxItem(typeof(MyUserControlToolBoxItem))]
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public string MyTextProperty { get; set; } = "Something";
}
public class MyUserControlToolBoxItem : ToolboxItem
{
protected override IComponent[] CreateComponentsCore(IDesignerHost host)
{
IComponent[] componentsCore = base.CreateComponentsCore(host);
if (componentsCore != null && componentsCore.Length > 0
&& componentsCore[0] is MyUserControl)
(componentsCore[0] as MyUserControl)
.MyTextProperty = "Something else"; ;
return componentsCore;
}
}
public class MyUserControlDesigner : ControlDesigner
{
public override void InitializeNewComponent(IDictionary defaultValues)
{
base.InitializeNewComponent(defaultValues);
var component = Control;
var eventBindingService = (IEventBindingService)this.GetService(
typeof(IEventBindingService));
var componentChangeService = (IComponentChangeService)this.GetService(
typeof(IComponentChangeService));
var designerHostService = (IDesignerHost)GetService(typeof(IDesignerHost));
var rootComponent = designerHostService.RootComponent;
var uiService = (IUIService)GetService(typeof(IUIService));
var designerTransaction = (DesignerTransaction)null;
try
{
designerTransaction = designerHostService.CreateTransaction();
var e = TypeDescriptor.GetEvents(rootComponent)["Load"];
if (e != null)
{
var methodName = "";
var eventProperty = eventBindingService.GetEventProperty(e);
if (eventProperty.GetValue(rootComponent) == null)
{
methodName = eventBindingService
.CreateUniqueMethodName(rootComponent, e);
eventProperty.SetValue(rootComponent, methodName);
}
else
methodName = (string)eventProperty.GetValue(rootComponent);
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($"{Control.Name}" +
$".MyTextProperty = \"Even something else!\";"));
}
componentChangeService.OnComponentChanged(rootComponent,
eventProperty, null, null);
eventBindingService.ShowCode(rootComponent, e);
}
designerTransaction.Commit();
}
catch (System.Exception ex)
{
if (designerTransaction != null)
designerTransaction.Cancel();
uiService.ShowError(ex);
}
}
}