Интерфейс
Last updated
Last updated
Как правило, расположение графических объектов формы задается относительно друг друга через координаты Top и Left, в редких случаях используются координаты Bottom, Right.
Например, на форме:
Панель HeadPanel является самой первой и ее координаты Top и Left будут задаваться относительно самой формы:
Координата Top всех нижележащих панелей будет привязываться к координате Bottom вышестоящей панели:
Координату Left для этих объектов задали константой относительно формы, но можно задать относительно координаты Left у HeadPanel .
Объекты внутри контейнера будут использовать аналогичную привязку друг к другу. Координаты Top, Left первого объекта задаются относительно контейнера:
А нижележащие объекты будут привязываться к вышестоящим:
Если между объектами нужно задать расстояние, то следует использовать универсальные значения Calculate или Formula:
Так как кнопка "Сохранить" выравнена по правому краю панели, то для задания ее положения используется координата Right:
Привязка координат объектов к другим объектам позволяет с меньшим усилием вносить изменения в положение объектов при добавлении новых объектов или изменении их размеров - не нужно вручную вычислять константные значения для каждого объекта. А также это отлично работает, если пользователь может менять размеры окна формы.
Тэг <Form>
содержит атрибут FormBorderStyle
, который задает тип границ окна формы. Если атрибут имеет значение Sizable, то пользователь может изменять размер формы. Чтобы при изменении размеров формы элементы интерфейса могли корректировать свои размеры, свойства Height и Width объектов должны описываться динамическими выражениями и привязываться к размерам контейнеров и самой формы.
Например, есть форма, которой можно менять размер:
Ширина всех панелей привязана к ширине формы:
А высота динамически будет меняться только у панели ContentPanel, для которой необходимо в тэге <Height>
указать выражение вида:
Таким образом, высота ContentPanel будет напрямую зависеть от высоты формы и высоты объектов ниже панели. Учитывая координату Top самой панели, не нужно дополнительно следить за размерами объектов выше панели.
Если контейнер, размер которого изменяется, содержит элементы, размер которых тоже должен изменяться, то в тэги <Height>
и <Width>
этих объектов следует прописывать динамические выражения. Панель ContentPanel содержит текстового поля "Описание", которое является многострочным (признак Multiline) и должно изменять свой размер. Для этого в тэг <Height>
объекта DescriptionTextBox необходимо прописать выражение:
Так же поля TitleTextBox и DescriptionTextBox изменяют и свою ширину. Это достигается тем, что в тэге <Width>
прописывается выражение, учитывающее ширину контейнера:
Ширину объекта DescriptionTextBox можно привязать к ширине объекта TitleTextBox:
Координаты <Top>
/<Bottom>
, <Left>
/<Right>
, <Height>
и <Width>
принимают целочисленные значения, поэтому если выражение задающее их значение содержит операцию деления, то необходимо использовать функцию округления.
Например, ширина объекта TitleTextBox должна составлять половину ширины контейнера с учетом отступа слева и справа:
Для округления используются следующие методы:
Floor(value)
- округляет вниз по направлению к отрицательной бесконечности;
Ceiling(value)
- округляет вверх по направлению к положительной бесконечности;
Truncate(value)
- округляет вниз или вверх по направлению к нулю;
Round(value, digits)
- округляет к ближайшему числу с заданным количеством знаков после запятой.
Элементы, назначение которых неочевидно или их текст неполностью передает его, то такие элементы должны сопровождаться всплывающими подсказками.
Например, кнопки могут иметь два варианта отображения: иконка с текстом и только иконка. Если кнопка имеет только иконку, то такая кнопка должна иметь подсказку определенную в тэге <Hint>
.
Состояние кнопки может изменяться динамически, при этом подсказка все равно должна быть:
Подсказки могут быть и на других объектах, например, на Panel, чтобы пояснить логику полей, описанных в панели:
Главное, показать пользователю, что при наведении курсора мыши в конкретное место, он получит подсказку. На скриншоте выше о наличии подсказки говорит иконка со знаком ворпроса.
К подсказкам на элементах относится и подсказка при срабатывании конструкции <Checking>
:
Такие подсказки могут не только говорить, что поле обязательно для заполнение, но и говорить, как правильно его заполнить.
Если на форме есть поля, обязательные для заполнения, или поля чувствительные к правильности заполнения, то для них следует использовать конструкцию <Checking>
.
В тэге <ConditionExpression>
проверяется условие корректного заполнения поля, если условие не выполняется, то возле поля будет отображаться полоска, при наведении на которую будет отображаться текст подсказки из тэга <AsteriskHint>
.
Чтобы сохранение было недоступно, если обязательные поля не заполнены, необходимо создать условие для проверки срабатывания конструкций <Checking>
:
Свойства CheckingFired у формы вернет True, если сработал хоть один <Checking>
. Таким образом, проверка этого свойства избавляет от необходимости повторно описывать все условия корректности обязательных полей.
Дальше это условие можно использовать в <Execution>
или на кнопке "Сохранить".
Размер и цвет полоски задается в атрибутах FlatColor
и FlatWidth
описанных в тэге <Form>
. В атрибуте ValidationType
задается вид отображения <Checking>
формы:
Flat - Полоска слева от объекта;
Asterisk - "Звёздочка" справа от объекта
Если выбран вид Asterisk, то для настроек цвета используется атрибут AsteriskForeColor
, а для задания размера используется размер шрифта, указанного в атрибуте AsteriskFontStyle
.
Бывают случае, когда необходимо разделить логику обязательных полей на разные события. Например, есть форма заказа с кнопками "Сохранить" и "Печать". Часть полей будут основными и обязательными для заполнения и при сохранении заказа, и при печати бланка заказа. К таким полям можно отнести данные о клиенте, дата и номер заказа. А какие-то поля будут обязательными только для печати - позиции заказа. Если пользователь сохраняет изменения на форме, то проверка корректности заполнения должна проходить только для полей обязательных при сохранении.
Чтобы реализовать такое разделение обязательных полей, конструкция <Checking>
имеет вложенный тэг <Group>, который задает имя группы:
Где ShowAsteriskHintVariable - обычный Variable со значением False по умолчанию:
Это вспомогательная переменная, которая позволяет ограничить срабатывание проверки обязательных полей. При нажатии на кнопку "Печать" должна вызываться команда вида, которая будет запускать проверку полей обязательных для печати:
Чтобы ограничить выполнения команд на сохранение или печати, необходимо создать условия проверки срабатывания <Checking>
в конкретной группе:
Когда у объекта типа Button условие в тэге <Enabled>
имеет значение False, визуально кнопка становиться недоступной, и пользователь не понимает из-за чего. Поэтому кнопки всегда должны быть активны, а если условие не выполняется, то при нажатии на кнопку пользователь должен получать сообщение о том, что пошло не так и как это исправить.
Для быстрой и простой реализации такой функциональности у кнопки Button есть режим DisabledMode, который включается через тэг <DisabledMode>
. Кнопка всегда остается активной, даже если Enabled равен False, а при нажатии на "неактивную" кнопку форма будет показывать сообщение с текстом из тэга <DisabledText>
.
Например, кнопка для открытия формы на редактирование сущности, которая будет доступна, если выбрана запись в таблице DatabaseTable:
В некоторых случаях включать режим DisabledMode можно динамически. Например, для кнопки "Сохранить" в карточке сущности. Если пользователь открыл карточку сущности и еще не внес изменения, то кнопка "Сохранить" может быть неактивной. В этом случае режим DisabledMode может быть выключен. Но, как только пользователь изменит хоть одно поле на форме, режим DisabledMode следует включить и проверять корректность и полноту заполнения обязательных полей.
Условие FormChangedEqualCondition проверяет свойство FormChanged у формы, а условие MandatoryFieldsAreFilledEqualCondition - свойство CheckingFired у формы.