JAML Syntax - Athari/Alba.Jaml GitHub Wiki

XML/JSON syntax

Compared to XML, JSON is more limited: objects in JSON do not have "types" and "content". In JAML, type is specified in $ property, and content in _ property. Attributes remain as is. In case of XAML's "element attributes", full property name is not required. So XAML

<Button Visibility="Visible">
  <Button.ToolTip>
    <TextBlock Text="Tool tip text"/>
  </Button.ToolTip>
  <TextBlock Text="Button text"/>
</Button>

becomes JAML

{
  $: 'Button', Visibility: 'Visible',
  Tooltip: { $: 'TextBlock', Text: "Tool tip text" },
  _: { $: 'TextBlock', Text: "Button text" }
}

Note that quotes around property names are optional.

Dollar field

$ field can contain not only type of the object, but its identifier (x:Name/x:Key), visibility (x:ClassModifier/x:FieldModifier), and in case of Templates and Styles, also implicit keys (TargetType/DataType). The syntax is as follows:

[visibility] typeName [identifier [implicit identifier]]

Examples:

  • Button
  • Button btnCancel
  • private Button btnCancel
  • DataTemplate {~Button}
  • DataTemplate MyButtonTemplate {~Button}

Dollar field can be omitted if type of the object created is type of the property, or type of the item of the property, in case of collections. For example, type of RowDefinitions property implements IEnumerable<RowDefinition>, so specifying $: 'RowDefinition' is optional. The same with templates and data templates, if properties are of type ControlTemplate and DataTemplate.

Markup extension shortcuts

JAML contains shortcuts for many built-in markup extensions like Binding and StaticResourceExtension. The list of common ideas behind shortcuts is very short and should be easy to remember.

Shortcut Meaning
= Calculate value dynamically (mostly bindings)
@ Get value by key (mostly resources)
~ Get type
ref Get element by name

Complete list of markup extension shortcuts:

Shortcut Becomes
{@Key} {StaticResource Key}
{@=Key} {DynamicResource Key}
{~TypeName} {x:Type TypeName}
{static.TypeName.Property} {x:Static TypeName.Property}
null {x:Null} (native JSON type)
{tpl.Property} {TemplateBinding Property}
{=PropertyPath} {Binding PropertyPath}
{=} {Binding}
{=ref.controlName.PropertyPath} {Binding PropertyPath, ElementName=controlName}
{=this.PropertyPath} {Binding PropertyPath, RelativeSource={RelativeSource Self}}
{=tpl.PropertyPath} {Binding PropertyPath, RelativeSource={RelativeSource TemplatedParent}}
{=~TypeName.PropertyPath} {Binding PropertyPath, RelativeSource={RelativeSource AncestorType=TypeName}}
{=@{...}.PropertyPath} {Binding PropertyPath, Source={...}}
{= ${=Prop1} + 42 + ${=Prop2} } <Binding> or <MultiBinding> (see below)

Spaces can be inserted for readability in some places: {= ref.controlName.PropertyPath }

MultiBinding/Binding converter expressions

It is possible to write inline C# expressions in bindings using shortcut syntax. Sub-bindings are surrounded with ${...}. Expressions are converted into automatically generated IValueConverter or IMultiValueConverter implementations in code-behind. Note that currently all values are of type object, as defined by the interfaces, so type casting may be necessary. Checks for DependencyProperty.UnsetValue are added automatically.

For example, the following binding returns true if IsMouseOver == IsMouseDirectlyOver:

{= (bool)${=this.IsMouseOver} == (bool)${=this.IsMouseDirectlyOver} }

This JAML will be converted into the following XAML:

<MultiBinding Converter="{x:Static my:MainWin._jaml_MainWindowConverter1}">
    <Binding Path="IsMouseOver" RelativeSource="{RelativeSource Mode=Self}" />
    <Binding Path="IsMouseDirectlyOver" RelativeSource="{RelativeSource Mode=Self}" />
</MultiBinding>

If the expression contains only one sub-binding, it'll be converted to Binding, not MultiBinding.

C# expressions are considered to end on the first comma coming after the last sub-binding. If C# expression contains a comma after the last sub-binding, it can be extended up to the terminator ${}. Converter parameter can be accessed with the name param. For example:

{= string.Format("Visibility = {0}, Name = {1}", ${=this.Visibility}, param) ${}, ConverterParameter={@Name} }

To parse expressions, regular expressions are used. If your code contains unpaired curly brackets, like string.Format("{{{0}", value), you can use escape sequences or static methods in code-behind. Code-behind or static methods in other classes for converters is also advised if expression is complex.

Property shortcuts

JAML contains specialized syntax for some commonly used classes and properties.

Style and trigger setters

Style and trigger setters use the same syntax as normal properties. Setters are properties of a set object, where property name is setter's Property, and property value is setter's Value. For example:

{
    $: 'Style MyButtonStyle',
    set: {
        Width: 16, Height: 16,
        Background: 'Red'
    }
}

To set TargetName of a setter to controlName, change the property name to ref.controlName.PropertyPath. For example:

set: {
    'ref.btnCancel.Width': 16, 'ref.btnCancel.Height': 16,
    'ref.btnCancel.Background': 'Red'
}

Alternatively, to avoid quotes, 'ref.controlName.PropertyPath' can be written as ref$controlName$PropertyPath (this also applies to attached properties, $ is replaced with .).

Triggers

Triggers can be written as properties of on object within a style or a template, where property name is a binding, and property value is the trigger's content, which can contain set object. Trigger's Value is set to True. To convert binding value to boolean, you can use inline syntax of multi-bindings with C# expressions (see above). For example:

{
    $: 'Style CheckBox',
    on: {
        '{=this.IsChecked}': {
            set: { Background: 'Red', Foreground: 'Green' }
        },
        '{= (bool)${=this.IsMouseOver} && (bool)${=this.IsChecked} }': {
            set: { Background: 'Yellow', Foreground: 'Blue' }
        }
    }
}

In setters of triggers of templates, you can use ref.controlName.PropertyPath syntax (see above).

Additional property shortcuts

Currently the only additional shortcut is Grid$, which translates four integers into Grid.Row, Grid.Column, Grid.RowSpan, Grid.ColumnSpan respectively. The value can contain from one to four values. For example, Grid='2 3' translates into Grid.Row="2" Grid.Column="3".

Syntax highlighting in Visual Studio

You may have noticed that JAML files begin with "_=". Characters till the first { are ignored, and this fake variable assignment is added to make VS believe JSON or JAML file is a valid JavaScript file. To get syntax highlight, open Tools > Options > Text Editor > File Extension, enter jaml into Extension field, choose Script Editor in Editor drop-down, and click Apply. You can also repeat the procedure for json files if you wish.

⚠️ **GitHub.com Fallback** ⚠️