在 Form.cs 中生成自定义 C# 代码,同时在设计时在 Form1.cs 中删除用户控件

Posted

技术标签:

【中文标题】在 Form.cs 中生成自定义 C# 代码,同时在设计时在 Form1.cs 中删除用户控件【英文标题】:Generate custom C# code in Form.cs while dropping user control in Form1.cs at design time 【发布时间】:2020-01-16 05:27:14 【问题描述】:

我有一个可以在 Form1.cs[Design] 模式下拖放的用户控件。设计器将在 Form1.Designer.cs 中为该用户控件自动生成代码

我还想知道的是:目前我正在通过拖动将用户控件添加到表单中,我不会在我的 Form.cs 中生成指向该用户控件上的属性和控件的代码。

用户控制示例:

public partial class UserControl1 : UserControl

    public UserControl1()
    
        InitializeComponent();
    

    public string TextInTextBox
    
        get  return textBox1.Text; 
        set  textBox1.Text = value; 
    

所以现在当我将它拖到 Form1.cs[Design] 中的表单上时。我不会在我的 Form1.cs 中生成这样的部分代码:

public partial class Form1 : Form

    public Form1()
    
        InitializeComponent();
        AddText();
    

    // this code below to be auto-generated
    private void AddText()
    
        userControl11.TextInTextBox = "";
    

我认为我应该寻找继承或接口之类的东西,但我希望该用户控件的每个实例都发生这种情况。 如果有人能指出我要寻找什么,那就太好了。谢谢。

【问题讨论】:

能否请您发布您到目前为止所尝试的内容。这样我们才能更好地帮助您。 我构建了界面,用户 control1 继承了该界面。但是我必须在 UserControl1.cs 中分配该接口中的所有方法。这不是我想要的。我希望界面中的这些方法针对 Form1.cs 中的 UserControl1 的每个实例显示,以便用户知道他必须提供逻辑来填充该 UserControl1 的每个实例的公开属性。我显然搜索了它,但我认为我问错了问题。我需要的只是一个提示。 你可以Generate code or events when drag-drop a custom control from the toolbox,但是对于设置属性,这不是一个好主意。要设置属性,您应该使用标准机制,例如创建工具箱项或自定义设计器。 如果只是设置一个属性,那么为它设置一些初始值就足够了。它将由设计师序列化。例如,如果您在UserControl 中有此属性public string MyTextProperty get; set; = "SomeText";,那么当您将控件实例放在表单上时,将生成此代码this.myUserControl1.MyTextProperty = "SomeText"; 【参考方案1】:

通常,当您从工具箱中删除控件时想要分配属性时,您不需要手动生成代码,例如您可以轻松地做到这一点:

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!";

示例

这里是MyUserControlMyUserControlToolboxItemMyUserControlDesigner的完整代码。您可以评论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);
        
    

【讨论】:

Reza Aghaei 非常感谢您。这正是我想要的。你是明星。抱歉回复晚了,但有另一项任务,需要学习 Luhn 算法。 不客气@LechKrawczyk :) 为确保您在答案中得到所有分数,您可以评论Designer 和/或ToolboxItem 属性并关闭所有设计器并清理和重建解决方案并在窗体上放置一个控件实例并查看生成的代码以了解其工作原理。

以上是关于在 Form.cs 中生成自定义 C# 代码,同时在设计时在 Form1.cs 中删除用户控件的主要内容,如果未能解决你的问题,请参考以下文章

(Swift 4) 如何在 firebase 中生成自定义自动 id?

如何在php中生成自定义图像?

从安全沙箱(例如小程序)中生成自定义类

VS2015 C#的.cs文件打不开?

是否可以在调整频率的同时在 C# 中生成恒定的声音?

在C#一个程序中,将一个窗体中的数据传送到另一个窗体