PropertyGrid FAQ
Содержимое
От "копипастера"
Это репост оригинальной статьи размещённой здесь под авторством Алексея Кирюшкина. С момента опубликования стать прошло уже почти 15 лет и с того времени произошли некоторые изменения. Эта перепечатка материала попытка освежить код оригинальной статьи и сделать копию для себя любимого сообщества. Также я попробую добавить некоторые дополнительные детали, методы и приёмы использования.
Вступление
PropertyGrid – удобный компонент для визуального редактирования свойств объектов, либо по документации предоставляет интерфейс пользователя, который используется как обозреватель для свойств объекта. Объект для редактирования можно задать в дизайнере WinForms, либо непосредственно в коде:
Хотя PropertyGrid умеет редактировать многие стандартные типы изначально (см. ниже), чаще всего на практике требуется адаптировать элемент под собственные нужды. Также стоит упомянуть, что для своей работы PropertyGrid активно использует аннотации данных (аттрибуты) имена типов которых далее в тексте упоминаются без суффикса "Attribute" для экономии места и лучшего восприятия.
Как изменить отображаемое имя свойства и его описание?
В приведённом выше примере можно заметить, что по-умолчанию в PropertyGrid для отображаемого имени свойства используется его имя, а также пусто описание свойства. Так происходит потому что мы не декорировали свойство необходимыми атрибутами. Для изменения отображаемого имени свойства предназначен атрибут DisplayName, а его описания Description:
Как сгруппировать свойства по категориям?
Можно заметить, что свойства объекта помещаются в категорию Misc, если не указано другое. Указать же PropertyGrid категорию свойства можно атрибутом Category:
Как сделать свойство недоступным для редактирования?
Как заменить стандартные значения true/false в отображении свойств типа bool?
Для замены стандартных значений true/false при редактировании булевых свойств необходимо создать свой конвертер, унаследовав его от класса TypeConverter и пометить свойство одноименным атрибутом TypeConverter.
Дополнение от "копипастера"
Вышеприведённый пример хоть и является работоспособным, но всё таки обладает одним недостатком, а именно дублированием кода при необходимости иметь для разных булевых свойств, разные текстовые соответствия, напр. "Включено/Выключено", "Активен/Не активен", "Да/Нет" и т.д.. Поэтому я предлагаю добавить атрибут, который будет содержать текстовые значения для необходимого свойства, а конвертер будет их использовать. Для начала создаём атрибут (проверки опущены для экономии места):
Как заменить стандартное отображение имен членов перечисления?
Для этого декорируем атрибутом Description каждый член перечисления и реализуем свой конвертер наследовав его от EnumConverter:
Как показать иконку для каждого значения из перечисления?
Необходимо реализовать своего наследника UITypeEditor и в нём переопределить отрисовку:
Как организовать выбор значения из выпадающего списка, формируемого программно?
Необходимо реализовать TypeConverter, предоставляющий список, из которого можно будет делать выбор:
В данном случае возвращается список строк из настроек программы. Затем нужно задать этот класс в качестве параметра атрибута TypeConverter для редактируемого свойства:
Аналогично реализуется и выбор из списка фиксированных значений например double - см. класс PossibleValuesTypeConverter в тестовом проекте.
Как избавиться от ошибки "Конструктор для типа "System.String" не найден" при редактировании свойств типа StringCollection?
... открываются для редактирования в PropertyGrid, но при попытке добавить строку к списку выдается сообщение об ошибке "Конструктор для типа "System.String" не найден" (Constructor on type "System.String" not found):
Исправить положение можно добавив атрибут Editor со следующими параметрами:
Окно редактирования StringCollection примет при этом следующий вид:
Как реализовать отображение составного свойства?
Бывает так, что тип свойства является сложным объектом, также имеющим свойства и конечно хотелось бы иметь возможность редактировать свойства этого объекта в раскрывающемся списке. Для этого к классу, используемому в качестве типа составного свойства, необходимо применить атрибут TypeConverter с ExpandableObjectConverter в качестве параметра:
Задавать дополнительные атрибуты для редактируемого свойства не нужно:
Как организовать выбор файла с заданным расширением?
Для этого необходимо реализовать свой Editor наследуемый от FileNameEditor
После этого можно декорировать свойство:
Как организовать редактирование свойства в собственной форме?
Как организовать редактирование свойства в выпадающем списке?
Опять же, реализовать своего наследника UITypeEditor, отображающего выпадающий список с нужным control-ом, передать ему исходное значение редактируемого свойства и принять результат по окончании редактирования (ForeignLangsControl – составной UserControl c элементами, необходимыми для редактирования свойства):
Далее декорируем свойство:
Как скрыть пароль при редактировании?
Для этого необходимо декорировать свойство атрибутом PasswordPropertyText:
Как управлять видимостью свойства в зависимости от значения другого свойства?
Стандартный атрибут Browsable позволяет задавать видимость свойства в PropertyGrid только на этапе написания кода. Чтобы управлять видимостью свойства в зависимости от значения другого свойства настраиваемого объекта, понадобится новый атрибут - DynamicPropertyFilter и базовый класс – FilterablePropertyBase:
Указываем базовый класс для класса настраиваемого объекта:
А для свойства, видимость которого зависит от другого свойства – атрибут DynamicPropertyFilter:
Также нужно добавить обработчик события PropertyGrid.PropertyValueChanged:
В данном случае свойство PersonalFileName (Имя файла личного дела) будет показано в PropertyGrid только тогда, когда свойство EmployeePosition (Должность) будет иметь любое из указанных в атрибуте значений:
Если переключить свойство Должность в значение, отсутствующее в параметре атрибута DynamicPropertyFilter, свойство Личное дело исчезнет из списка отображаемых свойств:
Аналогично, вторым параметром атрибута DynamicPropertyFilter можно передавать значения параметров других типов, например, перечисления или bool:
Решение не красивое, так как делает данные зависимыми от средств отображения и редактирования.
Как избавиться от стандартного "(Collection)" в правой колонке для свойств-коллекций?
Для этого необходимо реализовать CollectionTypeConverter:
И далее использовать CollectionTypeConverter как параметр в атрибуте TypeConverter:
При переходе к редактированию коллекции отобразится стандартное окно CollectionEditor с данными редактируемой коллекции:
Как заменить стандартные подписи (Members, properties) в окне Collection Editor?
"Members", "properties", "Add" и "Remove" можно заменить русскими аналогами переключением CurrentUICulture,как это сделано в методе Main() тестовой программы:
Однако, если надпись "Члены" над списком телефонов вас тоже не устраивает, можно применить и более радикальный способ. Заодно решим и следующую проблему.
Как добавить в Collection Editor окно с расширенной подсказкой по редактируемым свойствам?
Реализуем потомка CollectionEditor - PhoneNumbersCollectionEditor, который умеет запоминать положение и размеры своего окна, меняет стандартные подписи на соответствующие редактируемым данным и добавляет окно с расширенной подсказкой по свойствам:
Далее добавляем к свойству-коллекции атрибут Editor со специализированной версией CollectionEditor:
Как задать отличный от алфавитного порядок следования свойств внутри категории?
Нужно реализовать новый атрибут для задания порядка сортировки – PropertyOrderAttribute, и наследника ExpandableObjectConverter (PropertySorter), возвращающего список свойств, упорядоченный согласно значениям, заданным для них в атрибуте PropertyOrder:
Задаем атрибут TypeConverter с параметром PropertySorter для всего класса с настраиваемыми свойствами и указываем атрибут PropertyOrder для упорядочиваемых свойств:
Как запомнить и восстановить положение разделителя колонок в PropertyGrid?
Это можно сделать следующим образом:
Вызываются методы перед загрузкой и закрытием окна формы, содержащей PropertyGrid:






















Комментарии
Отправить комментарий