有关从WinForms中的C#属性生成GUI的提示

时间:2012-02-21 23:31:32

标签: c# winforms user-interface

上下文

我有一个非常多的小类或结构。这些类的实现细节并不重要,但是对于每个类都会有一些我想要公开的简单内置数据类型属性,以便可以在WinForms控件中对它们进行编辑。但是这些在不同的课程中会完全不同。例如:

class SleepAction : IGameAction
{
    public float Duration { get; set; }
}

class TeleportCharacterAction : IGameAction
{
    public string CharacterId { get; set;
    public string DestinationRoomId { get; set; }
    public Vector2 DestinationPosition { get; set; }
}

问题是我想要一个单个 WinForms控件,它能够编辑这些对象类型的所有。顶部会有一个所有类类型的下拉列表,当从此下拉列表中选择一个项目时,界面将更改为适应该类型的属性,以及创建该类型的实例来存储数据。

起初我正在考虑手工制作这些接口,可能使用TabControl对象,每个类一个选项卡,隐藏选项卡。但随后类的数量呈指数增长,所以我转向其他解决方案,可能使用属性和反射。我只是不确定如何开始。

我现在想到的是:

class ActionEditorControl : UserControl
{
    void ChangeEditorMode(Type type)
    {
        // Clear all GUI interface
        // Create object of type Type with default constructor
        // Use Type metadata to generate new GUI interface
        // Databind new interface to object properties
    }

    object GetObject()
    {
        // Return current object
    }
}

在我的模型对象上,我可以使用属性来添加必要的元数据:

class SleepAction : IGameAction
{
    [FieldLabel("Duration")]
    [FieldType("NumericSpinner")]
    public float Duration { get; set; }
}

class TeleportCharacterAction : IGameAction
{
    [FieldLabel("Character")]
    [FieldType("CharacterList")]
    public string CharacterId { get; set;

    [FieldLabel("Room")]
    [FieldType("RoomList")]
    public string DestinationRoomId { get; set; }

    [FieldLabel("Position")]
    [FieldType("VectorPicker")]
    public Vector2 DestinationPosition { get; set; }
}

当然,我需要教我控制如何解释这些属性。现在我的实际问题。

具体问题

  1. 这会有用吗?
  2. 有没有更好的替代解决我忽视的问题?
  3. 如何处理界面中控件的放置或布局?
  4. 最后,我以前从未使用过自定义属性。让我入门的好榜样?

2 个答案:

答案 0 :(得分:2)

是的,这应该有用,我已经构建了类似的东西来生成基于实体的动态搜索对话框。

自定义属性可以标识应该在表单上显示的属性。然后,表单可以为这些属性生成控件,并使用数据绑定将控件链接回对象上的属性。

TableLayoutPanel可以帮助生成控件的布局。一列可以存储标签对象,第二列可以存储控件(文本框等)。如果你想要更多的列,可以使用几组。

使用属性

由于您有类型,因此您可以在每个属性中搜索特殊属性:

foreach (var property in searchObjectType.GetProperties())
{
    var labelAttrib = (FieldLabelAttribute)property.GetCustomAttributes(typeof(FieldLabelAttribute), false).FirstOrDefault();
    var typeAttrib = (FieldTypeAttribute)property.GetCustomAttributes(typeof(FieldTypeAttribute), false).FirstOrDefault();
 }

表格面板:

一旦你知道你需要构建一个控件,弄清楚你要构建什么样的控件:(这假设你有一个带有Order属性的属性,所以你知道'在哪里'将控件放在网格中这个例子基于五个列,分别是标签,控制,间隔,标签,控制):

if (type == typeof(string))
{
  generatedControl = new Textbox();
  generatedControl.DataBindings.Add("Text", myObject, property.Name);
}

然后将控件添加到表中(假设您创建了一个标签控件):

pnlLayout.Controls.Add(label, (myAttrib.Order % 2 * 3), myAttrib.Order / 2);

pnlLayout.Controls.Add(generatedControl, (myAttrib.Order % 2 * 3) + 1, myAttrib.Order / 2);

答案 1 :(得分:1)

你所描述的内容听起来很像PropertyGrid