Генерация пользовательского C# кода в Form.cs при удалении пользовательского элемента управления в Form1.cs во время разработки - PullRequest
0 голосов
/ 16 января 2020

У меня есть пользовательский элемент управления, который я могу перетаскивать в режиме 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 [Дизайн]. Я не хочу, чтобы подобный код генерировался в моем Form1.cs:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        AddText();
    }

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

Я думаю, мне нужно искать что-то вроде наследования или интерфейса, но я бы хотел, чтобы это происходило для каждого экземпляра этот пользовательский контроль. Если бы кто-то мог указать мне направление, что искать это было бы здорово. Спасибо.

1 Ответ

1 голос
/ 16 января 2020

Обычно вам не нужно генерировать код вручную, если вы хотите назначить свойство при удалении элемента управления из панели инструментов, например, вы можете легко сделать это:

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);
        }
    }
}
...