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:
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:
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?
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);
}
}
}