Советы по созданию графического интерфейса из атрибутов C # в WinForms - PullRequest
2 голосов
/ 22 февраля 2012

Контекст

У меня есть очень большое количество небольших классов или структур .Детали реализации этих классов не важны, но для каждого из них будет несколько простых встроенных свойств типов данных, которые я хочу раскрыть, чтобы их можно было редактировать в элементе управления 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 ]

2 голосов
/ 22 февраля 2012

Да, это должно работать, я построил нечто подобное для генерации диалогов динамического поиска на основе сущностей.

Пользовательские атрибуты могут определять свойства, которые должны отображаться в форме. Затем форма может генерировать элементы управления для этих свойств и использовать привязку данных, чтобы связать элемент управления со свойством объекта.

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 голос
/ 22 февраля 2012

То, что вы описываете, очень похоже на PropertyGrid .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...