Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
… По сравнению с WPF это куцый огрызок, конечно,
Window root {
Resources: [
Style MyButtonStyle Button {
set: {
Background: Red, Foreground: Green
},
on: {
{=this.IsMouseOver}: {set: {
Background: Yellow, Foreground: Blue
}}
}
}
],
Grid {
RowDefinitions: [ { Height: * } ],
ColumnDefinitions: [ { Width: * } ],
Button btnPressMe {
Content: 'Press me!', Style: {@MyButtonStyle}
}
}
}
/* */. Причём поддерживает в любом месте, в то время как в XML нельзя, например, закомментировать атрибут. И эта проблема полностью отпадает при использовании собственного языка (пример см. в комментарии выше) — можно добавить ещё и строчные комментарии, чтобы было совсем как в C#.
{=this.IsMouseOver}: {set: { this.IsMouseOver: {set: {if: {
{= ${=this.IsMouseOver} && ${=this.IsChecked} }: {
set: {
ref.ExpandPath.Fill: '#FF262626,
ref.ExpandPath.Stroke: '#FF595959'
}
}
} Вот эквивалент на XAML: <MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsChecked" Value="True"/>
</MultiTrigger.Conditions>
<Setter TargetName="ExpandPath" Property="Stroke" Value="#FF262626"/>
<Setter TargetName="ExpandPath" Property="Fill" Value="#FF595959"/>
</MultiTrigger> (Если заменить && на ||, то в XAML возникнет ещё и конвертер OrConverter.)Когда я впервые в жизни вообще увидел код, и та было «i = i + 1»
{OrConverter {EqualsConverter {GetBindingByIndexConverter 0}, {GetBindingByIndexConverter 1}}, {EqualsToParameterConverter {GetBindingByIndexConverter 2}}} — это будет генерировать конвертер для выражения «a == b || c == null».<MultiTrigger>
<MultiTrigger.Conditions>
<ConditionGroup Mode="Or">
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsChecked" Value="True"/>
</ConditionGroup>
</MultiTrigger.Conditions>
<Setter TargetName="ExpandPath" Property="Stroke" Value="#FF262626"/>
<Setter TargetName="ExpandPath" Property="Fill" Value="#FF595959"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<ConditionGroup Mode="Or">
<ConditionGroup Mode="And">
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsChecked" Value="True"/>
</ConditionGroup>
<ConditionGroup Mode="And">
<Condition Property="IsMouseOver" Value="False"/>
<Condition Property="IsShitHappend" Value="True"/>
</ConditionGroup>
</ConditionGroup>
</MultiTrigger.Conditions>
<Setter TargetName="ExpandPath" Property="Stroke" Value="#FF262626"/>
<Setter TargetName="ExpandPath" Property="Fill" Value="#FF595959"/>
</MultiTrigger>
{
$: 'Button', Visibility: 'Visible',
Tooltip: { $: 'TextBlock', Text: "Tool tip text" },
_: { $: 'TextBlock', Text: "Button text" }
}
Button : {
Visibility : "Visible",
Text : "Hello World!",
Content : [
TextBlock : {
Text : {=Button.Text}
}
]
Tooltip : [
TextBlock : {
Text : "Tool tip text goes here"
}
]
}
{AncestorBinding (TreeViewItem.PropertyName).PropertyPath}, который извлекает тип из первого свойства (оно задаётся в полной скобочной записи). И эта штуковина работает через отражения, потому что мелкомягкие закрыли метод, который позволяет определять тип по строке. DictionaryKeyPropertyAttribute не работает в принципе, он поддерживается только для встроенных типов. Потомка Setter с нормально прописанным ContentPropertyAttribute создать нельзя. И так далее, и тому подобное.{Binding Path=Name, RelativeSource={RelativeSource AncestorType={x:Type Button}}, Converter={StaticResource Converter}}. Когда текста много, то это не только «наглядность», но и больше времени на прочтение кода, и меньше логики, умещающейся на одну страницу (мониторы пока не безразмерные). И когда я пишу <Setter.Value></Setter.Value>, я не устраняю каких-либо неоднозначностей, я вынужден писать эту конструкцию только из-за того, что разработчики забыли повесить на сеттер ContentPropertyAttribute.foreach-if-List.Add вместо Select-Where-ToList? И то, и другое можно делать кратким способом, обвешанным синтаксическим сахаром, и длинным, традиционным. Каким способом вы пишете?Думается мне, что реализация в форме runtime-библиотеки нецелесообразна. Сложная адаптация существующего кода, модификация типа проекта, build action'ы, парсер и кодогенератор. Всё это довольно приличный объем работы, и я бы сказал избыточный.
В студию добавляется расширение, которое добавляет новый редактор для XAML файлов. Открывая их вы видите уже JAML, и его же редактируете.
Зачем текст, если можно сделать структурированный редактор? Ведь XAML это дерево. Так я бы и сделал дерево, что бы можно было в узлах печатать текст. При этом не нужно замарачиваться с отступами, форматированием.
Альтернативный WPF язык JAML = XAML − XML + JSON