我正在尝试在Windows窗体中创建一个用户控件,它将具有“生成”子控件的功能。 示例:
假设我们的UC只有flowlayoutpanel
和ButtonText
属性:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<ButtonBlueprint> ButtonText { get; set; } = new List<ButtonBlueprint>();
ButtonBlueprint
只是字符串的包装,无所谓:
public class ButtonBlueprint
{
public string Name { get; set; }
}
我想要的并且我不知道如何实现是从该集合中的项目生成按钮。当你进入运行时很容易:
但我想在设计时将生成并在设计器中显示这些控件。 这可能吗?我知道一些高级控件,例如来自Telerik的高级控件具有类似的功能,可以从类模式生成控件,因此它应该是可能的。关于如何做到这一点的任何建议?
答案 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);
}
}
}