Язык выражений
Многие значения атрибутов — не константы, а выражения, вычисляемые относительно других свойств. Именно это делает дескрипторы динамическими: значение по умолчанию, зависящее от другого поля; строка, появляющаяся только при определённых условиях; подпись, отражающая текущую систему единиц.
1 Где используются выражения
Любой из этих атрибутов может содержать выражение вместо литерала:
DefaultValue,InchDefaultValue— вычисляемые значения по умолчанию.Visible,Enabled,ReadOnly— динамическое состояние (выражение должно давать логическое значение).Caption,Text,UnitsChar— вычисляемые строки для отображения.- ещё несколько, используемых отдельными подсистемами (например, флаги состояния ошибки).
Значение атрибута считается выражением, если содержит ссылку на свойство в скобках [...]
либо распознаваемую функцию/оператор. Простое значение вроде DefaultValue="1" или
DefaultValue="Millimeters" берётся буквально.
2 Ссылки на свойства: [...]
Ссылка в квадратных скобках разрешается в значение другого свойства.
Visible="[Enabled]"
DefaultValue="[ApproachFeed.ValuePerMinut]"
Разрешение имён
Голое имя вроде [Enabled] ищется в следующем порядке:
- соседи текущего свойства,
- цепочка родителей,
- глобальные свойства / объекты контекста в области видимости.
Поэтому [Enabled] рядом со свойством обычно означает «соседний Enabled».
Точечные пути
Точки позволяют заходить в составные типы и перемещаться по дереву:
DefaultValue="[ApproachFeed.LatheFeedRelativeMeasurement]"
Visible="[TechOperation.IsPrevOpInOtherChannel]"
Путь также может адресовать вариант перечисления по имени — [Group.LinearAxis] это
вариант LinearAxis перечисления Group. Сравнение свойства с одним из его вариантов —
идиоматический способ проверить перечисление:
Visible="[SimulationType] = [SimulationType.Painting]"
DefaultValue="([Group] != [Group.LinearAxis]) AND (([Max]-[Min]) GT 10000)"
Корни контекста
Помимо ближайших свойств, в качестве корней пути доступны некоторые объекты контекста, дающие выражениям доступ к более широкому окружению. Те, что встречаются чаще всего:
| Корень | Даёт доступ к |
|---|---|
TechOperation |
Операция, которой принадлежит свойство (флаги, соседи, информация о магазине, …). |
CAMApplication |
Состояние уровня приложения (например, [CAMApplication.PLMManager.ConnectionCount]). |
CurrentMeasurementsSystem |
Активная система единиц и её подписи. |
3 Аксессоры внутри [...]
Внутри ссылки можно вызывать аксессоры на разрешённом свойстве:
| Аксессор | Возвращает |
|---|---|
.Attribute(Name) |
Значение атрибута дескриптора Name (например, Caption, ItemIndex или любой пользовательский атрибут). |
.EnumValue |
Текущий выбранный вариант перечисления (можно дополнить .Attribute(Caption), чтобы получить его подпись). |
.Value |
Значение свойства явно (обычно подразумевается). |
.Count |
Количество элементов массива. |
<!-- подпись текущего выбранного варианта LinearUnits -->
DefaultValue="[CurrentMeasurementsSystem.LinearUnits.EnumValue.Attribute(Caption)]"
<!-- текущий индекс этого элемента массива, для самонумерующейся подписи -->
Caption="Point [Attribute(ItemIndex)]"
Внутри шаблона элемента массива $ParentNode ссылается на охватывающий элемент коллекции,
например Caption="Rule [$ParentNode.Attribute(ItemIndex)]".
4 Операторы
| Группа | Операторы |
|---|---|
| Арифметические | + - * / ^ (степень) DIV (целочисленное деление) MOD |
| Сравнения | = != <> < > <= >= и словесные формы LT GT LE GE |
| Логические | AND OR NOT |
Словесные формы существуют потому, что значения XML‑атрибутов заключены в кавычки, а
символьные </> неудобно читать рядом с разметкой — GT/LT/GE/LE обычно и
используются в реальных файлах. Скобки группируют подвыражения как обычно.
Visible="[Enabled] and ([StepCount] GT 1)"
DefaultValue="[UpperWorkLevel] + 5"
SupportShortestPathRotation DefaultValue="([Group] != [Group.LinearAxis]) AND (([Max]-[Min]) GT 10000)"
5 Функции
Условные — CASE, IF, SWITCH
Эти три покрывают почти всю реальную логику.
IF(условие, значениеЕслиИстина, значениеЕслиЛожь) — простой тернарный оператор.
DefaultValue="IF([SimulateToolChange], 'Auto', 'DoNotUse')"
CASE(...) — самый частый условный оператор в дескрипторах. В форме с двумя значениями
ведёт себя как IF: CASE(условие, значениеЕслиИстина, значениеЕслиЛожь). Он также допускает
цепочку: ряд пар условие, результат, вычисляемых по порядку, с необязательным финальным
значением по умолчанию.
<!-- форма if/else -->
DefaultValue="CASE([IsSpatial], 'SnapToWorkpieceCS', 'SnapToToolCS')"
<!-- цепочка: побеждает первое подходящее условие, последнее «голое» значение — по умолчанию -->
DefaultValue="CASE(
[HolderType]=[HolderType.LeftLatheSpindle], '1',
[HolderType]=[HolderType.RightLatheSpindle], '2',
-1)"
(реальный пример: Machines/MachineTypes.xml)
SWITCH(значение, вариант1, результат1, вариант2, результат2, …, по_умолчанию) — выбирает
по равенству с значением, как классический оператор switch. Удобно, когда одно свойство
отображается во множество исходов:
RotationsSequence DefaultValue="
SWITCH([ControlData.ToolFrameOutput.Format],
[ControlData.ToolFrameOutput.Format.EulerXYZ], 'XYZ',
[ControlData.ToolFrameOutput.Format.EulerXZY], 'XZY',
'XYZ')" <!-- финальное значение — по умолчанию -->
(реальный пример: Machines/AbstractMachine.xml)
Числовые функции
| Функция | Смысл |
|---|---|
MIN(a, b, …) / MAX(a, b, …) |
Минимум / максимум |
ABS(x) |
Абсолютное значение |
ROUND(x [, digits]) / SMARTROUND(x) |
Округление |
SQRT, EXP, LN, SGN/SIGN |
Базовая математика |
SIN, COS, TAN, ASIN, ACOS, ARCTAN, … |
Тригонометрия |
Строковые функции
| Функция | Смысл |
|---|---|
STR(x) |
Число → строка |
CHR(code) |
Символ по коду |
CONCATENATE(sep, s1, s2, …) |
Объединить строки через разделитель |
ISVALUEINSET(v, a, b, …) |
Истина, если v равно одному из перечисленных значений |
6 Строковые литералы
Строковые литералы внутри выражений записываются в одинарных кавычках: 'XYZ', 'Auto'.
DefaultValue="IF([SimulateToolChange], 'Auto', 'DoNotUse')"
7 Разобранные примеры
Значение, по умолчанию равное другому свойству — держать две подачи синхронными, пока их не изменили:
<ValuePerMinut DefaultValue="[ApproachFeed.ValuePerMinut]"
InchDefaultValue="[ApproachFeed.ValuePerMinut]"/>
Строка, появляющаяся только когда установлен флаг и количество имеет смысл:
<SCType ID="StepValue" type="Double" DefaultValue="1" DimensionKind="Linear"
Visible="[Enabled] and ([StepCount] GT 1)"/>
Значение перечисления по умолчанию, выбранное из состояния другого перечисления:
<SCType ID="DefaultState" type="Enumerated"
DefaultValue="if([RotaryTrans.TCPMAvailable] AND (NOT [RotaryTrans.TCPMDefault]), 'Auto', 'Off')">
<SCType ID="Off" type="none"/>
<SCType ID="Auto" type="none"/>
</SCType>
(реальный пример: Machines/AbstractMachine.xml)
Советы. Держите выражения свободными от побочных эффектов — они вычисляются при каждом обновлении интерфейса. Проверяйте сравнения перечислений через форму
[Enum.Option], а не строковые литералы, чтобы переименованный вариант падал явно, а не молча не совпадал. Когда выражениеVisible/Enabledссылается на свойство в другой ветви дерева, используйте полный точечный путь от известного корня.
Далее: Дескрипторы операций