Диалоговое окно динамических параметров (с использованием отражения)

2

Кто-нибудь знает о хорошем компоненте (С# WinForms), который позволит создать форму (настройки) формы, учитывая пользовательский класс с кучей свойств? Я не ищу что-то блестящее, но что-то просто лучше, чем сетка свойств. Я могу легко позаботиться о визуальной части, но я просто не хочу терять время, делая отражение, чтобы добавлять и связывать элементы управления, если они уже существуют.

Я уверен, что видел где-то раньше Visual Studio-подобную форму, которая была создана динамически (с некоторыми атрибутами, прикрепленными к свойствам класса, чтобы разрешить группировку и дополнительную информацию).

[Изменить] Например, у меня может быть класс параметров:

public class Options : SerializableOptions<Options>
{
     [Category("General")]
     [Name("User name")]
     [Description("Some text")]
     public string Username { get; set; }

     [Category("General")]
     [Name("Log in automatically")]
     public bool LogInAutomatically { get; set; }

     [Category("Advanced")]
     // ConnectionType is enum
     public ConnectionType ConnectionType { get; set; }

     // ...
}

После передачи его в эту форму он создаст две панели ( "Общие" и "Дополнительно" ), с CheckBox и TextBox на первой панели и один ComboBox (со всеми доступными перечислениями) на второй панели.

Если такого контроля нет, что вы, ребята, используете? Вручную добавлять, заполнять, форматировать и связывать элементы управления для каждой опции?

  • 0
    Winforms, WPF или WebForms?
  • 0
    Winforms, я обновил вопрос.
Теги:
reflection
winforms
binding
options

3 ответа

2
Лучший ответ

Я не знаю никаких элементов управления, которые позволят вам сделать это, но это не сложно сделать самому. Самый простой способ - создать диалоговую оболочку, пользовательский элемент управления, который действует как базовый класс для параметров "панели", один (или более) атрибут для управления именем и информацией о группировке и интерфейс (который реализует пользовательский контроль).

Каждая из ваших панелей настраиваемых параметров получается из пользовательского элемента управления и переопределяет какой-то метод Initialize() и Save() (предоставляемый пользовательским элементом управления). Он также предоставляет ваш атрибут (или атрибуты), который определяет информацию о названии/группировке.

В оболочке диалогового окна отразите все общедоступные типы из вашей сборки (или всех загруженных сборок), которые ищут типы, реализующие ваш интерфейс. Когда вы найдете тип, получите атрибуты, чтобы определить, где их разместить в вашей группе (проще всего использовать древовидное представление), вызовите Activator.CreateInstance, чтобы создать экземпляр пользовательского элемента управления и сохранить его в Tag имущество. Когда пользователь нажимает на запись в группе (дерево node), получите Tag и установите панель, которая содержит элемент управления пользователя для объекта в свойстве Tag. Наконец, когда пользователь нажимает "ОК" в диалоговом окне, прокручивайте узлы дерева, получите свойство Tag и вызовите метод Save.

Update: Другой вариант - использовать управление сеткой свойств. У него нет "симпатичного" пользовательского интерфейса, но он очень функциональный, он уже поддерживает группировку по атрибуту категории и обеспечивает большую гибкость. Вы можете пойти с единственной сеткой свойств, которая отображает все параметры, или пойти с "гибридным" подходом с древовидным представлением, которое группируется по основным функциям (плагин, возможности и т.д.), Вероятно, на основе типа. Когда пользователь нажимает кнопку node, дайте сетке свойств экземпляр объекта. Единственным недостатком этого подхода является то, что при внесении изменений в значения сетки свойств они "живут" в том, что базовое свойство немедленно изменяется, а это означает, что понятие "Отмена" не существует, кроме сохранения копии каждого значения, которое может изменить и выполнить какой-либо тип "reset" самостоятельно.

  • 0
    Но это означало бы, что я должен реализовать реальную функциональность для каждой панели. Я надеялся, что смогу передать экземпляр моего класса и заполнить эти панели автоматически (например, каждое свойство может иметь атрибут Category, который будет определять соответствующую панель).
  • 0
    @Groo: Вы также можете сделать это. Передайте экземпляр вашего класса методу Initialize панели, который затем рефлексивно проверяет свойства и заполняет сам себя. Самой большой проблемой будет правильное расположение элементов управления, ярлыков и т. Д. Намного проще написать панель самостоятельно.
1

Я случайно нашел нечто похожее на это, я помнил, что у меня была эта проблема некоторое время назад, и я подумал, что должен поделиться ею.

Вот простой пример: http://blog.denouter.net/2008/08/simple-reflection-form.html. Он использует отражение для создания нескольких элементов управления на основе свойств объекта.

1

Я не знаю, существует ли такой элемент управления, но написание требуемого кода отражения действительно не так сложно. Например. что-то вроде этого:

// the class for which to create an UI
public class MyClass
{
    public string Text { get; set; }
    public int ID { get; set; }
}

...

// basic reflection code to build the UI for an object
var obj = new MyClass() { Text="some text", ID=3};

foreach (var pi in obj.GetType().GetProperties())
{
    var name = pi.Name;
    var type = pi.PropertyType;
    var value = pi.GetValue(obj, null);

    //now setup the UI control for this property and display the value
}
  • 0
    Эта часть не будет сложной, но должна быть фабрика (словарь?) Для создания экземпляра и привязки надлежащего элемента управления к каждому свойству в зависимости от его типа. Это та часть (наряду с форматированием, правильной стыковкой и т. Д.), Которую я хотел избежать с нуля. Как я уже сказал, я мог бы реализовать это, но хотел бы знать, существует ли он уже.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню