1

I need to automate creation and configuration of several controls in the form while in design mode.

For things like that, I create a control that interacts and modifies some other controls in the form and sets default values, adds columns to grids,... Once done, I remove the control and that's it.

This is a not quite elaborate technique to create ad-hoc macros, but it works like a charm to ease repetitive work configuring properties, specially with "big" objects with a lot of elements like grids.

The problem is that I'm not able to create new controls and add them to the form dynamically while in design mode. Consider the following code (just a simplified example):

  public partial class ButtonCreator : UserControl

    [Category("Automation")]
    public int LeftPosition { get; set; }

    [Category("Automation")]
    public bool AutoCreate
    {
        get { return false; }
        set
        {
            var form = FindForm();

            if (value)
            {
                for (var i = 10; i < 100; i = i + 20)
                {
                    var button = new Button(){Name = "btn_" + DateTime.Now.Ticks + "_" + i};
                    form.Controls.Add(button);
                    button.Location = new Point(LeftPosition, i);
                    button.BringToFront();
                }
            }
        }
    }

(I've also tried using a component designer with a similar code, but with the same result, so this way is much less verbose)

To use this I add an instance of ButtonCreator to the Form, then I set the AutoCreate property (while in design mode, from the property list). Apparently It works and adds the buttons to the form, but they are not serialized to the autogenerated C# code and I lose them after saving.

Is there something I can do to force them to serialize when Visual studio generates the designer.cs file?

Consider this restriction: This is not code to be released, just dirty code to ease development, therefore I prefer to avoid more complex techniques to be able to introduce changes easily, right while coding. References to Visual Studio automation, or creating visual studio extensions should be avoided if possible.

Marco Regueira
  • 1,045
  • 8
  • 17
  • 2
    The designer knows beans about these added buttons. You can't select them and you can't get them serialized. This must be done by a designer, it must call IDesignerHost.CreateComponent(). See for example System.Windows.Forms.Design.TabControlDesigner.OnAdd(), the code that adds two TabPages to a TabControl when you drop one on a form. – Hans Passant Nov 12 '15 at 15:33
  • You may find my answer [here, about adding controls programmatically at design-time](http://stackoverflow.com/a/33535154/3110834) helpful. – Reza Aghaei Nov 12 '15 at 16:00
  • I think you should put the logic in a `Base Form` constructor or create your form using a `t4` template. – Reza Aghaei Nov 12 '15 at 16:04
  • @HansPassant, Thank you for your comment. That really does it. If you don't mind adding it as an answer I will gladly accept it. – Marco Regueira Nov 13 '15 at 06:16
  • Please write the answer yourself and accept it, you've got a much better snippet than I have. – Hans Passant Nov 13 '15 at 08:23
  • Thank you very much @HansPassant. I'll do. – Marco Regueira Nov 13 '15 at 08:51

1 Answers1

2

According to comment by Hans Passant, all that is needed is to ask the designer environment to create the object, so the new component can be tracked.

   var host = GetService(typeof(IDesignerHost)) as IDesignerHost;
   var button = host.CreateComponent(typeof(Button), "someName") as Button;
   FindForm().Controls.Add(button);
Marco Regueira
  • 1,045
  • 8
  • 17