Понятие, виды, соответствие типа данных и контрола, создание провайдера контролов, структура для обработки контролов различных типов данных

Провайдеры контролов - классы, наследующиеся от абстрактного ICSSoft.STORMNET.Windows.Forms.Binders.ControlProvider, предназначенные для привеления в соответствие типа контрола и типа объекта данных. Например, на универсальной форме редактирования.

У класса ICSSoft.STORMNET.Windows.Forms.Binders.ControlProvider имеется метод GetControl, возвращающий структуру ICSSoft.STORMNET.Windows.Forms.Binders.ControlForBindStruct, в которой и указывается соответствие контрола типу значения.

Существует так называемый стандартный провайдер контролов ICSSoft.STORMNET.Windows.Forms.Binders.StandardControlProvider, в котором метод GetControl перегружен таким образом, что возвращает контролы некоторым предопределённым образом.

Контролы, возвращаемые StandardControlProvider

Тип Контрол
string System.Windows.Forms.TextBox
System.Decimal
System.Double
System.Int16
System.Int32
System.Int64
System.SByte
System.Single
System.UInt16
System.UInt32
System.UInt64
System.Windows.Forms.TextBox
System.DateTime ICSSoft.STORMNET.Windows.Forms.DateTimePicker
bool System.Windows.Forms.CheckBox
Enum ICSSoft.STORMNET.Windows.Forms.ExtendedComboBox
ICSSoft.STORMNET.DetailArray ICSSoft.STORMNET.Windows.Forms.GroupEditBase
ICSSoft.STORMNET.DataObject ICSSoft.STORMNET.Windows.Forms.ComboLookup или (в зависимости от параметров) ICSSoft.STORMNET.Windows.Forms.LookUp.LookUp

Если требуется, чтобы редактировался другой тип, или другим контролом, необходимо определить собственный провайдер контрола и ассоциировать его с типом.

Существует несколько наиболее распространённых ситуаций:

  • Настройка контрола для редактирования значения стандартного типа;
  • Редактирование нестандартного типа стандартным контролом;
  • Редактирование нестандартного типа нестандартным контролом.

ControlForBindStruct

ICSSoft.STORMNET.Windows.Forms.Binders.ControlForBindStruct - структура, определяющая контрол для редактирования некоторого свойства. Например, Обработка даты в ControlProvider).

Для данной структуры определены три конструктора:

  • ControlForBindStruct(object control, string controlPropName) — экземпляр контрола, который будет редактировать значение;
  • ControlForBindStruct(object control, string controlPropName, Type[] typeMapping) — имя значимого свойства контрола, т.е. то, в которое устанавливается и возвращается значение;
  • ControlForBindStruct(object control, string controlPropName, Type[] typeMapping, IComponent[] additionalControls) — мапирование (цепочка явных, либо неявных преобразований) типов, используется в случае, когда значимое свойство не поддерживает напрямую нужный тип, но поддерживает другой, к которому нужный тип может преобразовываться. Если это мапирование указано, тогда при установке значения в свойство контрола преобразование происходит последовательно, по указанным типам, начиная с начала массива, а если обратно (при установке из свойства контрола в свойство объекта данных), то с конца массива.

Control

control - экземпляр контрола, который будет редактировать значение.

var txtbox = new System.Windows.Forms.TextBox();
var dateTimePicker = new ICSSoft.STORMNET.Windows.Forms.DateTimePicker();

ControlPropName

controlPropName - имя значимого свойства контрола, т.е. то, в которое устанавливается и возвращается значение.

Например:

  • для контрола типа System.Windows.Forms.TextBox : “Text”.
  • для контрола типа System.Windows.Forms.CheckBox : “Checked”.
  • для контрола типа System.Windows.Forms.ComboBox : “Text”.
  • для контрола типа ICSSoft.STORMNET.Windows.Forms.DateTimePicker : “ObjectValue”.

TypeMapping

typeMapping - это массив, используемый для маппирования типов значений, с которыми должен работать control.

Например:

1.Если значение типа System.String будет обрабатываться с помощью System.Windows.Forms.TextBox, то маппинг можно опустить:

new ControlForBindStruct(new System.Windows.Forms.TextBox(), "Text")

2.Если значение типа ICSSoft.STORMNET.UserDataTypes.NullableDateTime будет обрабатываться с помощью ICSSoft.STORMNET.Windows.Forms.DateTimePicker, который работает с типом System.DateTime, то необходимо выполнить маппинг (полный пример в статье Обработка даты в ControlProvider):

ControlForBindStruct(new ICSSoft.STORMNET.Windows.Forms.DateTimePicker(), "ObjectValue",
                            new System.Type[] {typeof(ICSSoft.STORMNET.UserDataTypes.NullableDateTime),
                                        typeof(System.DateTime)})

3.Если значение типа ICSSoft.STORMNET.UserDataTypes.NullableDecimal будет обрабатываться с помощью System.Windows.Forms.TextBox, который работает с типом System.String, то необходима цепочка маппинга, поскольку системе известно, как перевести ICSSoft.STORMNET.UserDataTypes.NullableDecimal в System.Decimal, а из System.Decimal уже в System.String.

ControlForBindStruct(new System.Windows.Forms.TextBox(), "Text",
                        new Type[] { typeof(ICSSoft.STORMNET.UserDataTypes.NullableDecimal),
                                        typeof(Decimal), typeof(string) }

Описание собственного провайдера контролов

На самом деле, во всех случаях, создание контрола происходит через стандартный провайдер контролов, однако предварительно стандартный провайдер проверяет ассоциированный с типом провайдер контрола. Стандартный провайдер возвращает предопределённые контролы только тогда, когда нет другого ассоциированного провайдера, или метод ассоциированного провайдера вернул null либо ControlForBindStruct.Empty.

Для того чтобы создать собственный провайдер контролов, необходимо унаследоваться от ICSSoft.STORMNET.Windows.Forms.Binders.ControlProvider и переопределить метод GetControl. Он имеет параметры:

  • string ApplicationType — тип приложения (некоторая строка, идентифицирующая тип пользовательского интерфейса);
  • Type type — тип, значения которого нужно редактировать контролом;
  • ICSSoft.STORMNET.View view — представление, в котором находится объект данных;
  • string propertyName — имя свойства объекта данных, которое нужно редактировать.

Пример можно посмотреть в статье DateTimePicker.

Возвращать контрол можно в зависимости от комбинации значений этих параметров, т.е. гибко настраивать пользовательский интерфейс.

Метод возвращает структуру ICSSoft.STORMNET.Windows.Forms.Binders.ControlForBindStruct при конструировании которой указывают:

  • System.Object control
  • System.String controlPropName
  • System.Type[] typeMapping

Примечание: связывание контрола со значением происходит через стандартный .Net-биндинг. Т.е. связываемый контрол должен «понимать» тип значений.

Ассоциирование провайдера контролов с типом

После того как провайдер создан, необходимо ассоциировать его с типом. Для этого служит атрибут ICSSoft.STORMNET.Windows.Forms.Binders.ControlProviderAttribute. Параметром указывается тип провайдера.

Например:

[ICSSoft.STORMNET.Windows.Forms.Binders.ControlProvider(typeof(ДеньгиTextBoxControlProvider))]
    public struct Деньги //Кстати, пример пользовательского типа
    {
        //И т.д.

Очевидно, что данный способ удобен для нестандартных типов. Но как быть со стандартными типами, к ним ведь никак нельзя приписать атрибут?

Существует ещё один механизм, установка провайдера контролов, обрабатывающего все типы. Чтобы выполнить это, следует установить в статическое свойство StandardControlProvider.ControlProviderForNotCustomizedTypes провайдер контролов.

Пример:

StormNetForms.Binders.StandardControlProvider.ControlProviderForNotCustomizedTypes=new РесурсControlProvider();

Настройка контрола для редактирования значения стандартного типа

Необходимо реализовать провайдер контролов и установить его в статическое свойство StandardControlProvider.ControlProviderForNotCustomizedTypes.

Редактирование нестандартного типа стандартным контролом

Необходимо реализовать провайдер контролов с указанием мапирования типов и ассоциировать его с типом, либо установить его в статическое свойство StandardControlProvider.ControlProviderForNotCustomizedTypes.

Редактирование нестандартного типа нестандартным контролом

Необходимо создать контрол для редактирования значений нестандартного типа.

Для этого:

  • Реализовать контрол как наследник от ICSSoft.STORMNET.Windows.Forms.Binders.BindableUserControl
  • Контрол обязательно должен иметь значащее свойство и событие, сигнализирующее об изменении значения, с именем ХХХХХChanged, где ХХХХХ — имя значащего свойства. Событие обязательно должно взводиться при изменении значения значащего свойства.
  • Контрол может имплементировать интерфейс ICSSoft.STORMNET.Windows.Forms.ICustomizableControl для более точной настройки в зависимости от класса данных, представления, имени свойства.
  • Контрол также может имплементировать интерфейс ICSSoft.STORMNET.Windows.Forms.IButtonizableControl специально для более удобного ввода значений через ICSSoft.STORMNET.Windows.Forms.GroupEditBase.

Далее необходимо реализовать провайдер контролов и ассоциировать его с типом, либо установить его в статическое свойство StandardControlProvider.ControlProviderForNotCustomizedTypes.

Общие замечания по провайдерам контролов

Поскольку тип и прочие параметры приходят в перегружаемый метод GetControl провайдера, разумеется, нет необходимости делать по одному провайдеру для каждого контрола. Можно использовать один на несколько типов или создать один провайдер контролов на всю систему и установить его в StandardControlProvider.ControlProviderForNotCustomizedTypes.