UserControl在设计时生成子控件

时间:2018-06-18 12:08:58

标签: c# winforms user-controls

我正在尝试在Windows窗体中创建一个用户控件,它将具有“生成”子控件的功能。 示例:

假设我们的UC只有flowlayoutpanelButtonText属性:

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

ButtonBlueprint只是字符串的包装,无所谓:

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

现在,我为这个系列设计了一个很好的编辑器: enter image description here

我想要的并且我不知道如何实现是从该集合中的项目生成按钮。当你进入运行时很容易:

enter image description here

但我想在设计时将生成并在设计器中显示这些控件。 这可能吗?我知道一些高级控件,例如来自Telerik的高级控件具有类似的功能,可以从类模式生成控件,因此它应该是可能的。关于如何做到这一点的任何建议?

1 个答案:

答案 0 :(得分:1)

嗯,您不仅需要在设计时生成子控件,还需要通过将更改序列化为* .Designer.cs来保留更改。如果我理解您的问题,您可以通过以下代码获得灵感。只是一个非常简单的示例(仅通过向* .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);
        }
    }
}