Thaven
Thaven

Reputation: 1897

UserControl generate sub-controls at design-time

I'm trying to create a user control in Windows Forms, with will have the function of "generating" subcontrols. Example:

Let say that we have UC with only flowlayoutpanel, and ButtonText property:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public List<ButtonBlueprint> ButtonText { get; set; } = new List<ButtonBlueprint>();

ButtonBlueprint is just wrapper for string, doesn't matter:

public class ButtonBlueprint
{
    public string Name { get; set; }
}

Now, I got a nice editor in designer for this collection: enter image description here

What I want and I don't know how to achieve is to generate buttons from items in this collection. It's easy when you kick in into runtime:

enter image description here

But i want to have those controls generated and being visible in designer while being during design-time. Is this possible? I know that some advanced controls, for example from Telerik has a similar feature and can generated controls from a class schema, so it should be possible. Any advice on how to do this?

Upvotes: 0

Views: 187

Answers (1)

Rexxowski
Rexxowski

Reputation: 180

Well, you need not only generating the subcontrols during designtime, but you also need to keep the changes by serializing them to *.Designer.cs.. If I understood your problem well, you can get inspired by following piece of code. Just a very simple sample (persistency done only by adding a comment to the *.Designer.cs).

using System;
using System.CodeDom;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Drawing;
using System.Windows.Forms;
using ControlDesigner = System.Windows.Forms.Design.ControlDesigner;

namespace WindowsFormsApp1
{
    [DesignerSerializer(typeof(TestSerializer), typeof(CodeDomSerializer))]
    [Designer(typeof(TestEditor), typeof(IDesigner))]
    public partial class TestControl1 : UserControl
    {
        public TestControl1()
        {
            InitializeComponent();
        }
    }

    public class TestEditor : ControlDesigner
    {
        private static int _counter;

        public TestEditor()
        {
            Verbs.Add(new DesignerVerb("Add button", Handler));
        }

        private void Handler(object sender, EventArgs e)
        {
            var button = new Button
                         {
                             Enabled = true,
                             Text = "Hello",
                             Name = string.Format("Button{0}", ++_counter)
                         };
            button.Location = new Point(0, _counter * button.Size.Height);
            ((TestControl1)Component).Controls.Add(button);
        }
    }

    public class TestSerializer : CodeDomSerializer
    {
        public override object Serialize(IDesignerSerializationManager manager, object value)
        {
            if (value.GetType() == typeof(TestControl1))
            {
                var serializer = manager.GetSerializer(typeof(TestControl1).BaseType, typeof(CodeDomSerializer)) as CodeDomSerializer;
                if (serializer != null)
                {
                    var coll = serializer.Serialize(manager, value) as CodeStatementCollection;
                    if (coll != null)
                    {
                        var tc = (TestControl1)value;
                        foreach (Control control in tc.Controls)
                        {
                            coll.Insert(0, new CodeCommentStatement("Component " + control.Name));
                        }
                    }

                    return coll;
                }
            }

            return base.Serialize(manager, value);
        }
    }
}

Upvotes: 1

Related Questions