Для тех, кто постоянно использует Visual Studio, панель Properties (Свойства), является одним из основных инструментов для редактирования свойств элементов, в первую очередь это касается графических примитивов в Windows Forms и WPF. Несомненно, такой элемент может быть полезен и в собственном проекте. Далее речь пойдет о том, как использовать PropertyGrid в приложении.
Введение
В рамках данной статьи мы создадим приложение, в при построении которого научимся работать с элементом PropertyGrid (сетка свойств).
Код проекта можно скачать здесь.
Типичное окно сетки свойств выглядит так:
Данный элемент предназначен для редактирования и отображения свойств различных объектов в удобном виде.
Свойства элемента могут быть сгруппированы по определенному признаку, либо выстроены по алфавиту. Каждое свойство имеет имя (левый столбец), значение (правый столбец) и описание (находится внизу окна). Свойство может быть изменяемым или неизменяемым.
В нашем проекте мы продемонстрируем работу со следующими типами свойств:
- текст;
- логическое значение;
- перечисление;
- цвет;
- шрифт.
Работу с динамически изменяющимися массивами, которые, тоже, несомненно, можно использовать в качестве значения свойств, мы рассмотрим в следующей статье, посвященной данной теме.
Для того, чтобы в проекте использовать сетку свойств необходимо:
- Создать в родительском элементе (например форме) объект класса PropertyGrid.
- Создать класс, описывающий определенный набор свойств. Каждое такое свойство конфигурируется посредством атрибутов.
- Создать объект класса свойств и присвоить его полям необходимые значения.
- Присвоить свойству SelectedObject объекта класса PropertyGrid объект с описанием свойств (созданный в пункте 3).
Создание каркаса приложения
Создадим новое приложение Windows Forms с именем “PropertyGridExample” и добавим на главную форму два элемента “ComboBox” и “PropertyGrid”.
Если в списке Toolbox нет элемента PropertyGrid, то его следует добавить. Для этого нажмите правой кнопкой мыши на панели Toolbox и выберите элемент меню “Choose Items…”.
На вкладке “.NET Framework Components” найдите в списке строку с именем “PropertyGrid” и отметьте ее галочкой.
Теперь на панели “Toolbox” у вас должен появиться элемент “PropertyGrid”.
Зададим следующие свойства родительской форме:
Свойство | Значение |
FormBorderStyle | FixedSingle |
Text | PropertyGrid Example |
Size | 340; 345 |
Элементу “ComboBox”:
Свойство | Значение |
FlatStyle | Flat |
(Name) | cbKindOfProps |
Location | 12; 12 |
Size | 310; 21 |
Items | Example of PropertyGrid for TextField
Example of PropertyGrid for True/False field Example of PropertyGrid for Categories Example of PropertyGrid for Color field Example of PropertyGrid for Font field Example of PropertyGrid for Enum |
Элементу “PropertyGrid”:
Свойство | Значение |
(Name) | prgProperty |
Location | 12; 42 |
Size | 310; 266 |
Должно получиться примерно следующее.
Создадим пустую папку с именем “PropertyClasses” в нашем приложении, для этого нужно щелкнуть правой кнопкой мыши на имени проекта в дереве решения окна “Solution Explorer” и выбрать “Add->New Folder”.
В созданную папку добавим файлы C# классов со следующими именами:
- PropertyTextField
- PropertyTrueFalse
- PropertyCategories
- PropertyList
- PropertyColorSelector
- PropertyFontConfig
После этого окно решения должно выглядеть примерно так:
Добавим обработчики событий для следующих элементов:
“Form1” (“Form”)
Событие | Функция обработчик |
Load | Form1_Load |
“cbKindOfProps” (“ComboBox”)
Событие | Функция обработчик |
SelectedIndexChanged | cbKindOfProps_SelectedIndexChanged |
Исходный код главной формы проекта приведен ниже.
using System; using System.Windows.Forms; using PropertyGridExample.PropertyClasses; namespace PropertyGridExample { public partial class Form1 : Form { private PropertyTextField prTextProp; private PropertyTrueFalse prLogicProp; private PropertyCategories prCategoryProp; private PropertyColorSelector prColorProp; private PropertyFontConfig prFontProp; private PropertyList prListProp; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { prTextProp = new PropertyTextField(); prLogicProp = new PropertyTrueFalse(); prCategoryProp = new PropertyCategories(); prColorProp = new PropertyColorSelector(); prFontProp = new PropertyFontConfig(); prListProp = new PropertyList(); cbKindOfProps.SelectedIndex = 0; } private void cbKindOfProps_SelectedIndexChanged(object sender, EventArgs e) { switch(cbKindOfProps.SelectedIndex) { case 0: prgProperty.SelectedObject = prTextProp; break; case 1: prgProperty.SelectedObject = prLogicProp; break; case 2: prgProperty.SelectedObject = prCategoryProp; break; case 3: prgProperty.SelectedObject = prColorProp; break; case 4: prgProperty.SelectedObject = prFontProp; break; case 5: prgProperty.SelectedObject = prListProp; break; } } } }
При загрузке формы в методе “Form1_Load” осуществляется инициализация объектов, которые являются демонстрацией использования тех или иных типов свойств. Метод “cbKindOfProps_SelectedIndexChanged” вызывается при выборе интересующего нас примера из выпадающего списка. Для управления сеткой свойств используется объект “prgProperty”.
Создание классов, описывающих разные типы свойств
Для управления видом свойства в окне “PropertyGrid” используются атрибуты, приведенные в таблице ниже.
Атрибут | Описание |
[Browsable(bool)] | Отображение свойства. Отображать (true) или не отображать (false) данное свойство в окне “PropertyGrid”. |
[ReadOnly(bool)] | Редактируемость свойства. Свойство с возможностью редактирования (true) или только для чтения (false) |
[Category(string)] | Категория свойства. Позволяет логически группировать свойства. |
[Description(string)] | Описание свойства. Будет отображено в нижней части окна PropertyGrid. |
[TypeConverter(System.Type)] | Задание вида свойства в окне PropertyGrid. |
Далее будут представлены классы, реализующие работу тех или иных типов свойств.
Тип свойства – текстовое поле.
class PropertyTextField { String m_TextField; [Browsable(true)] [Description("Example of text field")] [DisplayName("Text field")] public String TextField { get { return m_TextField; } set { m_TextField = value; } } }
Тип свойства – логическая переменная.
class PropertyTrueFalse { bool m_LogicField; [Browsable(true)] [Description("Example of logic field")] [DisplayName("Logic field")] public bool LogicField { get { return m_LogicField; } set { m_LogicField = value; } } }
Тип свойства – список.
class PropertyList { Direction m_dir; [DisplayName("Direction")] [Description("Direction property")] [TypeConverter(typeof(DirConverter))] public Direction Dir { get { return m_dir; } set { m_dir = value; } } }
Для того, чтобы данный список работал добавим перечисление “Direction”, элементы которого и будут содержаться в выпадающем списке.
enum Direction { [Description("UP")] UP, [Description("DOWN")] DOWN, [Description("RIGHT")] RIGHT, [Description("LEFT")] LEFT }
Также определим класс “DirConverter” для преобразования элементов перечисления “Direction” в строковое представление. Тип этого класса указывается в качестве параметра атрибута “TypeConverter” класса перечислительного свойства.
class DirConverter : EnumConverter { private Type type; public DirConverter(Type type) : base(type) { this.type = type; } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType) { FieldInfo fi = type.GetField(Enum.GetName(type, value)); DescriptionAttribute descAttr = (DescriptionAttribute)Attribute.GetCustomAttribute( fi, typeof(DescriptionAttribute)); if (descAttr != null) return descAttr.Description; else return value.ToString(); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { foreach (FieldInfo fi in type.GetFields()) { DescriptionAttribute descAttr = (DescriptionAttribute)Attribute.GetCustomAttribute( fi, typeof(DescriptionAttribute)); if ((descAttr != null) && ((string)value == descAttr.Description)) return Enum.Parse(type, fi.Name); } return Enum.Parse(type, (string)value); } }
Тип свойства – цвет.
class PropertyColorSelector { Color m_ColorField; [Browsable(true)] [Description("Example of color field")] [DisplayName("Color field")] public Color TextField { get { return m_ColorField; } set { m_ColorField = value; } } }
Тип свойства – шрифт.
class PropertyFontConfig { Font m_FontField; [Browsable(true)] [Description("Example of font field")] [DisplayName("Font field")] public Font FontField { get { return m_FontField; } set { m_FontField = value; } } }
Демонстрация разбиения свойств на категории.
class PropertyCategories { String m_TextParam1; [Browsable(true)] [Description("Property: Text param 1")] [Category("Text params")] [DisplayName("Text param 1")] public String TextParam1 { get { return m_TextParam1; } set { m_TextParam1 = value; } } String m_TextParam2; [Browsable(true)] [Description("Property: Text param 2")] [Category("Text params")] [DisplayName("Text param 2")] public String TextParam2 { get { return m_TextParam2; } set { m_TextParam2 = value; } } bool m_LogicParam1; [Browsable(true)] [Description("Property: Logic param 1")] [Category("Logic params")] [DisplayName("Logic param 1")] public bool LogicParam1 { get { return m_LogicParam1; } set { m_LogicParam1 = value; } } bool m_LogicParam2; [Browsable(true)] [Description("Property: Logic param 2")] [Category("Logic params")] [DisplayName("Logic param 1")] public bool LogicParam2 { get { return m_LogicParam2; } set { m_LogicParam2 = value; } } }
Приложение PropertyGridExample
Запущенное приложение “PropertyGridExample” выглядит так.
В выпадающем списке нам предлагаются примеры, демонстрирующие работу различных типов свойств. На рисунке выше показано текстовое свойство. Далее по списку – логическое свойство.
Демонстрация разделения свойств на группы.
Выбор цвета.
Задание шрифта.
Выбор элемента из заданного списка.
Работа с PropertyGrid довольно проста, достаточно разобраться с основными моментами, которые необходимо учитывать при его использовании. На этом все, спасибо за внимание!