Альтернативный WPF язык JAML = XAML − XML + JSON

    На дворе наступал Новый год, а из головы никак не выходила мысль, что XAML может быть лучше. И, чтобы ему быть лучше, ему нужно перестать быть. Так родилась затея написать альтернативу кошмарному и ужасному XAML'ю: без <Setter.Value>, без {Binding Path=Name, RelativeSource={RelativeSource AncestorType={x:Type Button}}, Converter={StaticResource Converter}}, без FirstValueEqualsToSecondValueOrThirdValueEqualsNullConverter, без <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions>, без <MultiDataTrigger> <MultiDataTrigger.Triggers> <DataTrigger> <DataTrigger.Binding> <MultiDataBinding>..., без xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml", без всего этого барахла, от написания которого в десятый раз возникают позывы нежно погладить компьютер табуретом и вспоминаются далёкие индусские родственники разработчиков WPF.



    Фичи:
    • Тёплый ламповый синтаксис JSON без кавычек вместо дьявольских уголовых скобок XML.
    • Краткий и вменяемый синтаксис для markup extensions: километровые один-раз-написал-потом-читать-страшно-байндинги {Binding Path=Name, RelativeSource={RelativeSource AncestorType={x:Type Button}}, Converter={StaticResource Converter}} превращаются в почти присваивания {= ~Button.Name, Converter={@Converter} }.
    • Кошерные выражения на C# на замену некошерным конвертерам: {= ${=Property1} == ${=Property2} || ${=Property3} == null }.
    • Смерть «элементной» записи свойств — <Setter.Value> уходят в небытие.
    • Зубодробительное повторение повторений объявляется устаревшим: если куда-то можно положить только ColumnDefinition, не надо повторять это десять раз.
    • Сеттеры и триггеры перестают быть многобуквенными сериализованными костылями: сеттеры выглядят как присваивание свойств, триггеры выглядят как условия.
    • Смерть дублированию десяти «clr-namespace» с указанием имён соборок и прочей нечисти.

    Звучит классно? А выглядит оно так:

    _={
        $: '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}'
            }]
        }]
    }

    Когда/если допилю язык, будет выглядеть примерно так:

    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}
            }
        }
    }


    Сначала немного о грустном: это не библиотека, которую можно засунуть в проект, чтобы сразу стало хорошо. Это Proof-Of-Concept. Смысл написания библиотеки — доказать, что её можно написать, что не разверзнутся врата Ада, что работающий код может быть написан за вменяемый срок.

    На разработку ушло немногим больше недели (да-да, я именно так провожу новогодние праздники). Вчера писал документацию на гитхабе, сегодня пишу эту статью. Поэтому к библиотеке не прилагается и прилагаться не может следующее: поддержка типов помимо встроенных во фреймворк, вменяемые и воспринимаемые человеками сообщения об ошибках, безбажность хотя бы в простых случаях, юнит-тесты.

    Сейчас решительно закрыла вкладку в браузере наша прагматичная половина читателей. С идеалистами и мечтателями — продолжаем.

    Для тех, кто хочет попачкать ручонки и не брезгует документацией на кривом английском — прошу в гости на гитхаб. Там в ReadMe и Wiki вся необходимая информация: процесс установки, синтаксис и прочее. Здесь — то же самое, но более кратко.

    О странностях

    Возможно, вы обратили внимание, что файл начинается с "_=". Это фиктивное присваивание убеждает Visual Studio, что файл — это самый что ни на есть JavaScript, а не какой-то неведомый природе JSON (к сожалению, даже в 2013 году редактора JSON не существует в природе, такие дела). Дополнение кода (IntelliSense) мы и так теряем, а так, покопавшись в настройках (Tools > Options > Text Editor > File Extension), мы можем получить подсветку и проверку скобок хотя бы на уровне Script Editor.

    JSON по сравнению с XML довольно ограничен: у его «объектов» нет ни «типа», ни «содержимого». Поэтому тип (то, что в XML после <) задаётся денежным свойством "$", а внутренности (то, что в XML между и ) — свойством "_". Это временное неудобство, я подумываю над изменением языка. Посему XAML
    <Button Visibility="Visible">
      <Button.ToolTip>
        <TextBlock Text="Tool tip text"/>
      </Button.ToolTip>
      <TextBlock Text="Button text"/>
    </Button>
    приобретает вид JAML
    {
      $: 'Button', Visibility: 'Visible',
      Tooltip: { $: 'TextBlock', Text: "Tool tip text" },
      _: { $: 'TextBlock', Text: "Button text" }
    }

    Ещё в денежное свойство можно заложить информацию про идентификатор (x:Name/x:Key), видимость (x:ClassModifier/x:FieldModifier), а в случае стилей и триггеров ещё и «неявные» ключи (TargetType/DataType). Полный синтаксис (квадратные скобки — опциональность):
    [visibility] typeName [identifier [implicit identifier]]
    Примеры:
    Button
    Button btnCancel
    private Button btnCancel
    DataTemplate {~Button}
    DataTemplate MyButtonTemplate {~Button}

    Как уже было сказано, денежное свойство можно опускать, если тип «очевиден» (то есть свойство, в которое мы кладём объект, сообщает, что в него можно класть: T для IEnumerable<T>, ControlTemplate для ControlTemplate).

    О markup extension'ах

    JAML содержит огромное количество сокращений синтаксиса встроенных «расширений разметки», но в корне всех сокращений заложено очень маленькое (и, надеюсь, легко запоминаемое) количество идей:
    Сокращение Значение
    =
    Вычислять значение динамически (по большей части байндинги)
    @
    Получить значение по ключу (по большей части ресурсы)
    ~
    Получить тип
    ref
    Получить элемент по имени
    А теперь — полный список.
    Сокращение Одним вызовом T4 превращается в неизящный...
    {@Key}
    {StaticResource Key}
    {@=Key}
    {DynamicResource Key}
    {~TypeName}
    {x:Type TypeName}
    {static.TypeName.Property}
    {x:Static TypeName.Property}
    null
    {x:Null} (родной тип JSON)
    {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> или <MultiBinding> (см. ниже)
    Можно по вкусу разбавлять выражения пробелами: {= ref.controlName.PropertyPath } (но не переусердствуйте: всё-таки там внутри помесь слоноподобных регулярок с костыльными IndexOf, приправленные выковыренными потрохами System.Xaml).

    О выражениях и конвертерах

    Теперь в байндингах можно писать выражения на C#. Суб-байндинги создаваемого мульти-байндинга (или байндинга, если суб-байндинг один) заключаются в скобки ${...}. За кулисами выражения превращаются в классы, реализующие интерфейсы IValueConverter и IMultiValueConverter. Не нужно забывать, что в конвертеры приходят object'ы, то есть обычно без преобразования типов не обойтись (автоматическое определение типов выражений — в планах). Напротив, проверки на DependencyProperty.UnsetValue не нужны — проверка добавляется сама.

    Ближе к делу. Вот пример, в котором значением байндинга является IsMouseOver == IsMouseDirectlyOver:
    {= (bool)${=this.IsMouseOver} == (bool)${=this.IsMouseDirectlyOver} }
    Это конвертируется в следующий XAML:
    <MultiBinding Converter="{x:Static my:MainWin._jaml_MainWindowConverter1}">
        <Binding Path="IsMouseOver" RelativeSource="{RelativeSource Mode=Self}" />
        <Binding Path="IsMouseDirectlyOver" RelativeSource="{RelativeSource Mode=Self}" />
    </MultiBinding>

    Отделение выражения на C# от аргументов расширения разметки — для регулярных выражений задача непосильная, и единственное, что они могут — это проверить парность фигурных скобок. Собственно, выражение заканчивается на первой запятой после последнего суб-байндинга. Если такое поведение вас не устраивает, то можно задать конец выражения явно с помощью ${}. Например:
    {= string.Format("Visibility = {0}, Name = {1}", ${=this.Visibility}, param) ${}, ConverterParameter={@Name} }
    Ещё вам не повезло, если фигурные скобки непарные (типа string.Format("{{{0}", value) — не знаю, зачем надо, но мало ли) — тут вам в помощь эскейп-последовательности.

    Если выражение получается слишком сложное, то можно либо написать статический метод в code-behind, либо вынести логику в вообще другой класс — по вкусу.

    О сеттерах в стилях и триггерах

    Оные записываются как обычные свойства у объекта в свойстве «set».
    {
        $: 'Style MyButtonStyle',
        set: {
            Width: 16, Height: 16,
            Background: 'Red'
        }
    }
    Если нужно задать Setter.TargetName, то используйте синтаксис ref.controlName.PropertyPath.
    set: {
        'ref.btnCancel.Width': 16, 'ref.btnCancel.Height': 16,
        'ref.btnCancel.Background': 'Red'
    }
    Если вы ненавидите скобки вокруг имён свойств, то можно писать доллары вместо точек: ref$controlName$PropertyPath (доллар в JavaScript и JSON считается полноценным символом, в JAML он заменяется на точку). Такой же способ работает с attached properties.

    Триггеры пишутся в объект «on». Имя свойства — байндинг. Значение — внутренность триггера (в том числе с объектом «set»). Можно писать байндинги-выражения, как описано выше. Триггер считается сработавшим, если он принимает булево значение True. Например:
    {
        $: 'Style CheckBox',
        on: {
            '{=this.IsChecked}': {
                set: { Background: 'Red', Foreground: 'Green' }
            },
            '{= (bool)${=this.IsMouseOver} && (bool)${=this.IsChecked} }': {
                set: { Background: 'Yellow', Foreground: 'Blue' }
            }
        }
    }
    Синтаксис ref.controlName.PropertyPath в триггерах шаблонов тоже работает.

    Ну, и на закуску свойство Grid$ — оно принимает от одного до четырёх целых чисел и превращает их в Grid.Row, Grid.Column, Grid.RowSpan, Grid.ColumnSpan, соответственно. Пишешь Grid$='2 3' — получаешь Grid.Row="2" Grid.Column="3".

    Ссылки


    Выражаю благодарность авторам Json.NET, T4MultiFile, а также индусам, чей код я выковыривал из потрохов System.Xaml, чтобы распарсить «расширения разметки».

    Что дальше?

    Сейчас непонятно, что с этим экспериментом делать, потому что есть куда более срочные дела, чем изменение мира (кушать-то хочется). Скорее всего, через некоторое время вернусь к проекту и доведу до состояния, когда могу использовать в своём реальном проекте. А пока мне интересно мнение окружающих: надо ли оно? будет ли кто-нибудь использовать? нужно переписать с нуля, или можно довести до ума имеющееся?

    Пожалуй, самое большое неудобство со своим языком — это что поддержка всякими Решарперами отсутствует в принципе. Рефакторинг XAML решарпером сосёт и причмокивает, но он хоть какой-то есть. Плюс спустя шесть лет после появления WPF в решарпере таки родили хоть какую-то работу с DataContext и прочим. Если шесть лет ушло на официальный со всех сторон XAML, то про какой-то левый язык — и мечтать не приходится. И сбоку через плагин, наверное, ничего не приделать. В общем, придётся писать JAML, но постоянно заглядывать в XAML. Впрочем, как по мне, так всё равно лучше.

    В общем, какие мысли? Как вам затея?

    Only registered users can participate in poll. Log in, please.

    Ваше мнение о JAML?

    Share post

    Similar posts

    Comments 103

      0
      Круто было бы заставить это работать под Java (определённые платформы, типа Linux), и Android в частности! Тогда бы у вас была своя библиотека, подобная WPF, но со своим форматом и стандартами, не зависящая ни от кого.
        +1
        Это всего лишь синтаксическая обёртка над WPF, а не какая-то отдельная библиотека UI. Так как WPF в Mono нет и вряд ли когда-нибудь будет, то и Jaml, соответственно, бесполезен. Насколько я понимаю, Мелкомягкие скрыли слишком много потрохов WPF, чтобы разработчики Mono могли взяться за портирование.

        Оракл JavaFX пилит же, не? По сравнению с WPF это куцый огрызок, конечно, но кто знает, может, и одолеют что-то сопоставимое.
          0
          Это ясное дело. Но согласитесь, классно было бы вообще чтоб под Linux было полноценное подобие WPF для Java?
          Язык есть, осталось реализовать библиотеку — кто-то ж должен начинать с каких-то примитивов :)
            0
            JavaFX?
              0
              QML? Правда, там плюсы и js. Но есть байндинги и к другим языкам.
              –1
              … По сравнению с WPF это куцый огрызок, конечно,

              Не могли бы вы написать несколько весомых доводов/пояснений, почему JavaFX является куцым огрызком в сравнении с WPF?
                0
                Ну я быстро поглядел документацию, там и не пахнет чем-то сравнимым с WPF или Qt. Если вы хотите развёрнутый разбор, то вопрос не по адресу: я не пишу на Java, я не пользуюсь JavaFX. Если вы считаете, что WPF и JavaFX в одной весовой категории, то не исключено, что я проглядел что-то важное.
                  0
                  По правде говоря, я не считаю, что они в одной весовой категории. Я считаю, что JavaFX уже стала на голову выше. С момента появления JavaFX 2. Я, разумеется, могу привести и доводы, но пока хотелось бы несколько Ваших.

                  Развёрнутый разбор не нужен. Просто тройка пунктов вида — JavaFX есть огрызок потому, что там нет/плохо сделано таких вещей как…… которые крайне важны и до совершенства отточены в WPF.
                    0
                    Я ленив, поэтому stackoverflow.com/questions/2016470/how-does-javafx-compare-to-wpf

                    Вкратце:
                    1. Разметка не компилируется.
                    2. Построитель сцен на голову ниже Бленда (хоть и круче дизайнера VS).
                    3. Байндинги в коде, а не описываются декларативно.
                    4. Контролы — чёрные коробки. Шаблонов нет. Свойств мало.

                    Четвёртый пункт — самый критичный и решающий. Сила WPF — в том, что не нужно создавать класс «Кнопка с картинкой», ты просто пишешь шаблон или просто засовываешь это в контент. Можно положить любой контрол в любой контрол. Писать 100500 классов кнопок, как принято в WinForms — не надо.

                    За достоверность и актуальность сравнения на StackOverflow — ответственности не несу.
                      0
                      Вы действительно очень ленивы. Ибо даже не удосужились прочитать, что ваша ссылка на StackOverflow уже неактуальна и closed as not constructive. Она была создана в 2010 году до появления JavaFX 2 и сейчас полностью устарела. Все ваши пункты давно закрыты.

                      А почитав детальнее, вы возможно бы в чём-то и свой велосипед не изобретали бы. :)
                        0
                        На SO закрываются все вопросы-сравнения и прочие вопросы, не имеющие чёткого и однозначного ответа. Согласно политике партии, вопросы для SO должны быть в форме «у меня проблема, я решал её так, получилось так, но нужно так, что делать».

                        Второй ответ к вопросу (по которому я и составлял список), написан в октябре 2012 года, отредактирован в ноябре 2012-го, и в его тексте явно упоминается JavaFX 2.0, то есть теоретически ответ должен быть актуален.

                        Ладно, шут с ним, с SO. Вот допустим, что я хочу, чтобы каждый элемент дерева содержал два чекбокса, выпадающий список и текст с переносом слов, при наведении текст становился жирным, при подгрузке значений в выпадающий список под ним плавно появлялась и пропадала анимация с крутящимся колёсиком (но только если операция занимает больше 200 мс), при превышении максимальной длины текста он обрезался и писалось многоточие. Данные в дерево должны подгружаться из базы данных, причём только в открытые ветки. При выборе значения из выпадающего списка элемент дерева должен менять свой фоновый цвет. Как вы реализуете это в JavaFX? Опишите в общих чертах.

                        (В WPF некоторые из перечисленных требований реализуются через анус — никакой предвзятости. :) )
                          0
                          Да, верно. SO закрывает дискуссию, если вопрос не попадает в формат Да/Нет. Но, на самом деле SO хитрый. :) Он не против того, что бы люди пообсуждали и такие вопросы. И закрывают они их только если вопрос стал реально неактуален.

                          Вот гляньте на вашу ссылку. Судя по первому ответу (январь 2010) и до закрытия, прошло почти три года! Почти три года SO позволял обсуждать этот вопрос. :)

                          По поводу Вашей задачи… я не очень понял проблему. В JavaFX свойства контролов объявлены как собственный тип Property (IntegerProperty, DoubleProperty...). Все они реализуют ObservableValue интерфейс и байндинг с другими свойствами. То есть я могу прицепиться к событиям изменения свойства явно (если мне нужна сложная обработка) или связать его с другим свойством, если условие простое (типа навёл мышь — поменялся цвет)

                          Другими словами, не вижу никакой проблемы реализовать ваш сценарий стандартными средствами. Возможно будут нюансы, тружно сказать. Вещь пока новая. Сам разбираюсь неспешно. Да и развивается очень быстро.
                            0
                            Вы верно плохо знакомы с SO. Там активным закрывательством не всегда занимались, и сейчас закрыто множество старых, всё ещё актуальных, но «неформатных» вопросов. Если сейчас подобный вопрос живёт, то лишь потому что модераторы проглядели. Нет там никакого слежения за актуальностью вопросов и ответов.

                            Я спрашивал в первую очередь не про байндинги (как я понимаю, в JavaFX и WPF они устроены по-разному, но в целом функционал и идеи близки). Меня интересуют шаблоны. Как вы опишете размещение контролов в элементе дерева — как разместите в элементе дерева чекбоксы, списки и текст? Как эти контролы будут взаимодействовать друг с другом — они могут напрямую обратиться друг к другу и к данным? Вы сможете описать это декларативно в FXXML, или нужно будет писать процедурный код, или для конфигурации понадобятся дополнительные конфиги? Как вы будете описывать анимацию и логику её срабатывания на изменения значений свойств — декларативно в FXXML или создавая объекты процедурно, запуская анимации в обработчиках событий? Как будет реализовано взаимодействие с внешним источником данных — вы опишете некую модель, при изменении которой будут меняться, добавляться и удаляться элементы, или же вы будете явно оперировать элементами дерева?
                              0
                              Насчёт SO — наверное соглашусь. Трудно сказать как и почему они вдруг закрыли тут и не закрыли там. Возможно, действительно модераторы не успевают.

                              По поводу остального… Ну, вы вываливаете фейерверк довольно общих вопросов, ответ на каждый из которых это маленькая лекция. Что-то типа — ну а как ваша машина поедет, как работает ваш двигатель, как вы гарантируете работу тормозов, где вы добываете топливо…

                              Контролы я размещаю не просто в элементе дерева, а в элементе дерева который умеет распологать контролы в пространстве по умному. Это так называемые Layout панели. Их несколько разных родных и появляются новые сторонние в силу открытости. Они и будут отвечать за правильное расположение.

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

                              Байндинг на данные я могу декларативно описать в FXML.

                              С внешними источниками данных я могу взаимодействовать сотней разных способов. Например создать модель, которая будет содержать поля Properties и они будут автоматически связаны со свойствами контролов.

                              Беспредметный какой-то разговор.

                              Я пока не вижу никакого такого дефекта, который позволил бы назвать JavaFX огрызком по сравнению с WPF.
                                0
                                По-моему, пойнт вопроса был в том, как в JavaFX перерисовать внутренности контрола, не меняя класса. В WPF все проперти остаются на месте, а их визуализация меняется.
                                  0
                                  Я действительно не очень въезжаю о каких мифических шаблонах идёт речь.

                                  Что бы стилизовать приложение/контрол существует много способов. Разумеется, что строя сцену вы можете указывать разные значения свойств и действий на события как параметры инициализации контролов или же создавая анонимные классы для более сложного поведения.

                                  Далее, не меняя класса, вы можете стилизовать сцену, корневой узел, любой из узлов или все нужные типы узлов (скажем, радиокнопки) путём указания им собственных CSS. Поддерживается версия CSS 2.2 с элементами 3.0 и собственными расширениями. Скажем вы можете указать параметр shape для контрола как SVG цепочку рисовки и контрол будет перерисован как вы хотите.

                                  Для списков элементов существует возможность описать свою фабрику, которая будет предоставлять ваш собственный Cell для рисовки в данном списковом элементе.

                                  Если этого мало, то вы можете просто написать свой класс отвечающий за Skin контрола и воткнуть его туда. Вся рисовка делегирована в этот класс.
                                  Если вам мало обработчиков событий, вы можете полностью написать свое поведение контрола путём реализации своего класса Behavior. Эта часть будет более открытой в Java 8.

                                  Если вам нужна анимация, то вы можете создать несколько объектов называемых TimeLine, которые описывают как будут меняться кадры и привязать их к свойствам любых узлов сцены. Они будут в своём потоке анимировать контролы.

                                  Можно связать свойства в цепочки, тем самым также обеспечивая зависимость свойств одних контролов от значения других. Упрощённо говоря, поменялось значение, автматом поменялся цвет и положение.

                                  Ну вот навскидку варианты…

                                  Нашёл тут на SO вопрос человека из мира WPF. Он также искал какие-то templates и не мог понять, что подходы есть разные. Там также есть развернутый ответ:
                                  stackoverflow.com/questions/12383533/javafx-2-0-style-template-existing-control

            +19
            Синтаксис обилием долларов/собачек/скобочек/etc напоминает perl. -10 к читабельности.
              +6
              В первой версии не хотел изобретать свой язык, поэтому решил использовать JSON как есть. А в идеале планируется что-то вроде этого:

              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}
                      }
                  }
              }
              
              –1
              Ещё могу сказать, что в JSON мне не нравится по сравнению с XML:
              1) нет поддержки комментариев в спецификации
              2) иногда в больших файлах не видно за что отвечает закрывающая скобка, приходится трассировать глазами. В XML же видно название закрывающего тэга.
                +1
                Не знаю, что там в спецификации, но Json.NET поддерживает комментарии /* */. Причём поддерживает в любом месте, в то время как в XML нельзя, например, закомментировать атрибут. И эта проблема полностью отпадает при использовании собственного языка (пример см. в комментарии выше) — можно добавить ещё и строчные комментарии, чтобы было совсем как в C#.

                Что касается второй проблемы, то как вы читаете код C#? :) Там ведь нет endforeach и endclass.
                  0
                  Классно, что хоть в Json.NET добавили, а то приходится извращатся. А с атрибутами — да, порой раздрожает.
                  Читаю C#, думаю, как и многие :) Приходится глазами искать открывающуюся скобку :) С другой стороны, XML — слишком избыточный, но этот недостаток устраняется при комплиции XAML в BAML.
                +10
                image

                XAML в разы лучше в плане читабельности и удобства. Там конечно свои косяки, но его хотя бы практически любой может без проблем прочитать и тут же переварить полученную информацию.
                  +5
                  У вас два тезиса: «XAML лучше» и «XAML все понимают». Их надо бы отделить, один не вытекает из другого. :)

                  XAML «все понимают» не потому что он такой хороший, а потому что, не понимая его, нельзя разрабатывать на WPF. Разумеется, JAML — новый язык, и никто его знать не может. С этим спорить бесполезно.

                  А вот почему XAML лучше — объясните, пожалуйста, чем. Так как в планах замена JSON на более подходящий язык, то нужно определить критерии выбора синтаксиса.
                    0
                    Я не пишу на XAML и не разрабатываю софт на WPF (winforms мне гораздо ближе). Тем не менее я без проблем могу описать что делает код на XAML сходу. Чтобы описать что делает код на JAML мне понадобится какое-то время чтобы понять что все это делает и при этом не факт что я пойму.

                    Так что на текущий момент главный плюс на котором выезжает XAML перед JAML это то что он читается «легко и непринужденно» любым программистом (а может даже и не программистом).
                      +1
                      Насчёт читаемости мне судить сложно, потому что XAML знаю вдоль и поперёк, но вот точно помню, что писать его — точно не «легко и непринуждённо». Помню, как мне выносила мозг необходимость писать Setter.Value, не забывать указывать TargetType у всех стилей и шаблонов, как долго я вкуривал все возможные комбинации Binding, MultiBinding, Trigger, DataTrigger, MultiTrigger, MultiDataTrigger, чем отличаются TemplateBinding от Binding RelativeSource=TemplatedParent и прочее, и прочее, и прочее.
                        0
                        Ну я могу сказать так — пока это хотя бы немного не приблизилось к habrahabr.ru/post/165943/#comment_5727225 не думаю что это намного лучше XAML
                          +1
                          Проблема в избыточных свойствах "$" и "_" и кавычках, или вам выбор выражений а-ля {=this.Property} тоже не по душе? Так-то допилить язык — вопрос времени.
                            0
                            Ну для начала можно было бы заменить код в стиле
                            {=this.IsMouseOver}: {set: {
                            на
                            this.IsMouseOver: {set: {

                            А дальше уже отталкиваться от этого
                              0
                              По сути вы предлагаете вариант Qt. Это радикальное решение, которое сделает байндинги из всех выражений, независимо от того, хочет ли этого разработчик. За такое изменение меня гарантированно тухлыми помидорами закидают, потому что WPF и так скоростью не блещет, а это может обернуться ещё бОльшими проблемами. Я вынужден оставаться в рамках логики XAML.
                          0
                          > как долго я вкуривал все возможные комбинации Binding, MultiBinding, Trigger, DataTrigger, MultiTrigger, MultiDataTrigger

                          В XAML нет ни одного из этих слов.

                          Вы вкуривали в WPF, а не в XAML. Научитесь уже отделять язык от библиотеки.
                            0
                            Мне лень каждый раз писать «Extensible Application Markup Language in Windows Presentation Foundation». Если я пишу «XAML», я подразумеваю абракадабру выше. Должно быть ясно из контекста. И вообще, XAML в 99% случаев используется в WPF и всей его родне типа сервелата и метрозамля, и изначально создан он для WPF. Развели буквоедство.
                              0
                              Дело не в том «где используется», дело в том, что это не DSL для WPF. Это сериализованное представление объектов. И не более. И от изучения кишок самого WPF избавить даже не задумывался. Поэтому там написано xmlns=«schemas.microsoft.com/winfx/2006/xaml/presentation». А «изначально создан он для WPF» — это фантазии.

                              А ваша замена «Binding» на "=" от изучения внутреннего мира WPF, в виде всего вышеперечисленного, помогает только до первого ойбля-эффекта. То есть не спасает. Потому, что, например, в xaml понятно как clr-namespace подключать, а вы замены не предложили.

                              Зато можно покороче формочки с hello world описывать.
                          0
                          В том числе и непрограммистом. Это еще и язык, ориентированный на «слегка тренированных дизайнеров» + Blend
                            0
                            Как по мне, так XAML (тут примеры посмотрел) совершенно нечитабелен при отсутствии опыта работы с XML. YAML/JSON/JAML читаются в разы легче.
                        • UFO just landed and posted this here
                            +1
                            Давайте на момент забудем про решарперы, потому что XAML и JAML, очевидно, находятся в разных весовых категориях. Давайте оценивать исключительно синтаксис. Вот пример на JAML (я позволил себе наглость использовать «будущий» синтаксис без переизбытка кавычек):
                            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.)

                            Если показать эти куски кода тому, кто не очень-то разбирается в WPF, то что ему будет легче понять?

                            Можно вообще пойти по пути QML из Qt: выбросить к чертям все явные байндинги и просто писать чистые выражения…
                              +4
                              Как человек ниразу не писавший на WPF с уверенностью говорю, что пример на XAML гораздо понятней и яснее)

                              ${= просто убивают мозг.
                                0
                                А если без бакса? :) (Не рассматривал этот вариант, нужно думать, но это вполне может оказаться возможным.)
                                  +1
                                  вы пытаетесь избавить людей от страшных знаков больше и меньше в xml, при этом создавая не менее визуально ужасные конструкции имхо.
                                  +1
                                  Мне тоже, стало непонятным выражение с первого взгляда, но знаете, прочитав короткую спецификацию всё становится ясно и вполне читаемым. Думаю, это дело привычки.
                                  Когда я впервые в жизни вообще увидел код, и та было «i = i + 1» — это было жутко с моей математической точки зрения, я не мог понять как такое равенство может существовать. Познакомившись с программированием, конечно же все вопросы отпали :)
                                    0
                                    Я видел написанный кем-то BindToExtension, наследующийся от Binding и позволяющий кратко записывать свойство Path. Там было по символу на каждый случай жизни: "#" — имя элемента, "%" — TemplatedParent и т.п. Как по мне — запомнить все символы нереально. Поэтому при определении синтаксиса для JAML я выбрал минимум спец-символов (=, @, ~, $) — и дал им общий везде смысл. Если что-то забыто, всегда можно вывести из этих символов.

                                    Когда я впервые в жизни вообще увидел код, и та было «i = i + 1»

                                    Эх, припоминаю, как мне в школьные времена выносила мозг сишная арифметика на указателях и забавы типа a[b]==b[a]. %)
                                  0
                                  Зачем OrConverter? Можно два простых триггера написать. Правда сеттеры при этом придется продублировать.
                                    0
                                    Именно, что продублировать. А если сеттеров много? Дублирование кода — вообще зло: исправишь в одном месте, забудешь или опечатаешься в другом…
                                      0
                                      Да, это минус, поэтому такой хак только в простых случаях использовать можно. С другой стороны, OrConverter пишется только один раз, поэтому и его использование тоже не должно большой сложности представлять. В данном примере больше показательно то, что MS не развивает XAML с момента его создания, т. к. реализовать какой-нибудь ConditionGroup.Mode (Or, And, Xor) не представляет никакой сложности
                                        0
                                        По-моему, если сериализовать C# выражения в XML, получится ужас, летящий на крыльях ночи. Уже сейчас вы можете реализовать несколько десятков markup extension'ов, чтобы записывать конвертеры для мульти-байндингов «декларативно»: {OrConverter {EqualsConverter {GetBindingByIndexConverter 0}, {GetBindingByIndexConverter 1}}, {EqualsToParameterConverter {GetBindingByIndexConverter 2}}} — это будет генерировать конвертер для выражения «a == b || c == null».
                                          +1
                                          Я имел в виду нечто более XAML-подобное:
                                          <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>
                                          
                                            +1
                                            Причем эту идею можно развить до более функциональной, но не менее легко читающейся:
                                            <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>
                                            
                                              0
                                              Ну это же ужас. Вся эта конструкция выглядит интересной затеей только до тех пор, пока она одна. А если весь стиль утыкан такими монстрами — что-то понять и разобрать невозможно. Плавали, знаем.

                                              Это всё можно записать в одну строчку одним выражением на C#.
                                                0
                                                У вас часто в разметке попадаются сложные проверки? Я мультитриггеры с мультибиндингами крайне редко использую. Просто со стороны МС было бы неплохо предоставить инструмент, пусть даже и неудобный, но работающий. А ужас — это записать эту же конструкцию маркап экстеншнами или вложенными мультиконвертерами.
                                  0
                                  Тем не менее, эксперименты всегда хороши, даже если 95% заканчиваются неудачами. Ведь пока никто не предложит альтернативу, никто не сможет сказать что уже существуещее — лучше всего (потому что даже сравнивать не с чем).
                                +1
                                Ещё один убийца XML:)

                                «у нас был один неудобный формат. Мы захотели сделать новый и удобный. Теперь у нас два неудобных формата»
                                  +2
                                  Есть Razor. Есть QML. Есть HAML. Вы отрицаете их успешность?
                                    0
                                    Я отрицаю провал и неудобство XML:)
                                      +1
                                      Ну то есть HAML не нужен? Это же исключительно альтернативная запись HTML (который почти XML).
                                        +1
                                        Haml — это запись xhtml, который не «почти», а и есть xml
                                  0
                                  А что лучше XML? :)
                                  (думаю, стоит уточнить «для каких целей»)
                                    +1
                                    Правда, мне кажется с синтаксисом всё же мудрено. Уж как-то не по душе '_' и '$'.
                                    Вместо этого:
                                    {
                                      $: 'Button',  Visibility: 'Visible',
                                      Tooltip: { $: 'TextBlock', Text: "Tool tip text" },
                                      _: { $: 'TextBlock', Text: "Button text" }
                                    }
                                    

                                    Хочется в том же JSON формате видеть:
                                    Button : {
                                      Visibility : "Visible",
                                      Text : "Hello World!",
                                      Content : [
                                        TextBlock : {
                                          Text : {=Button.Text}
                                        }
                                      ]
                                      Tooltip : [
                                        TextBlock : {
                                          Text : "Tool tip text goes here"
                                        }
                                      ]
                                    }
                                    

                                    Подумайте с точки зрения как человек набирает код в JAML — если начинать кнопку с открывающей фигурной скобки, а тип прописывать аж в "$", то это будет сложно для Intellisense. А так набираешь 'B', в подсказке «Button», Tab — вставляет «Button: { }».
                                      0
                                      На самом деле необязательно писать "_", можно писать и «Content». Просто у разных объектов контентное свойство разное, запоминать сложно. Запись Button: { ... } не подходит, потому что по логике это свойство объекта, а не вложенный объект, и нет никаких способов отличить эти два случая.
                                      0
                                      В читабельности предлагаемый вариант XAML'у безусловно проигрывает, одни забубенные _ и $ чего стоят. Вот эта конструкция ужасна: {= ${=this.IsMouseOver} && ${=this.IsChecked} }: {

                                      Идеи избавления от избыточного синтаксиса здравые, но могут быть реализованы и в рамках XAML, было бы только желание разработчиков. Перечислять 30 раз одинаковые RowDefinition чудовищно.
                                        0
                                        Причём часть этих идей может быть реализована (а часть этой части уже реализована) при помощи behavior-ов. Например, для избавления от тех-же RowDefinition я находил класс, который позволяет просто задать количество строк и столбцов у Grid-а.
                                          0
                                          Обычно как минимум у одного столбца или строки свойства отличаются, поэтому подобные behavior'ы мало где применимы.
                                          0
                                          Вы можете предложить вариант лучше?
                                            0
                                            Выжать из XAML всю «воду» + улучшения для удобства.
                                          +3
                                          Если хотите делать язык человеко-читаемым, — используйте в качестве основы YAML, а не JSON.

                                          А еще лучше смотреть в сторону Slim, и делать по образу и подобию.
                                            0
                                            Нормальной работающей библиотеки для YAML не существует в природе ни под один язык кроме руби, к сожалению. Мне идея YAML нравится, но это равносильно написанию языка с нуля. YAML скорее мёртв, чем жив.

                                            Переписывание Slim с руби — из той же оперы.
                                              0
                                              Тот же Slim — это переосмысленный Jade (JavaScript), для которого есть реализации для многих языков.

                                              Ну а касательно парсеров YAML, — тот же парсер Ruby использует libyaml, для которой биндингов просто море. Обертка называется Psych.

                                                0
                                                Любопытно. Если Руби работает через сишный Либ-Ямль, который поддерживает Ямль 1.1, то спецификация Ямль 1.2 — трёхлетней давности, кстати о птичках — для кого вообще существует?
                                                  0
                                                  А какая разница, если хватает более ранней спецификации?
                                                    0
                                                    Меня сильно напрягает, когда последняя версия формата с очевидными преимуществами (совместимость с JSON) не поддерживается никем в природе, когда при близком рассмотрении куча библиотек для чтения формата содержат длинный список того, какие у них глюки, и что они не поддерживают. Это тонко намекает на то, что формат скорее мёртв, чем жив.

                                                    Та же ситуация с XSLT, например (и всем зоопарком XML'ных языков). Если мелкомягким нафиг не впёрлось обновление до версии 2.0, то эти языки можно считать мёртвыми, даже если кто-то умудряется их применять (ИМХО, возможность вставлять процедурный код в XSLT перекрывает все новые фенечки, но это уже не «тру», разумеется).

                                                    Да и сам YAML — тоже не сказка. Да, он во многом мощнее и «читабельнее», чем JSON, но мусор вроде "!!str" будет напрягать разработчиков не меньше, чем мои "${=}".

                                                    В общем, если выбирать альтернативный язык для WPF, то самым привлекательным выглядит изобретение своего велосипеда, как ни парадоксально. Если кому-то нужно будет работать с форматом другими средствами, то можно будет воспользоваться парсером из библиотеки же.

                                                    Спасибо за ссылки, конечно, но я вряд ли ими воспользуюсь.
                                                0
                                                Visual Studio YAML Editor yaml.codeplex.com/
                                                YamlSerializer for .NET yamlserializer.codeplex.com/
                                                Yaml Library for .NET yaml-net-parser.sourceforge.net/default.html
                                              0
                                              XAML редактор сильно ругали за отсутствие autocomplete и подсказывания контекста, с json это еще сложнее. Вы уверены что оно того стоит?
                                                0
                                                Ну писали же как-то на XAML без нормального автокомплита. :)
                                                  0
                                                  Справедливости ради, отмечу что с Resharper 7.1 и выше, редактирование XAML стало довольно приятным. Решарпер реально помогает.
                                                    0
                                                    Да, но прошло шесть долбаных лет с появления WPF, пока джетбрейны сделали что-то вменяемое. Жалко, что они сами WPF не используют толком — если бы сами ели, разработка могла бы стать вменяемой гораздо раньше.
                                                  +1
                                                  Да что же вы все пристали к этому XAML. Работаю с WPF с момента выхода и никогда не возникало проблем. Поставьте себе уже Решарпер. Или напишите свой markup extension и используйте его. Мое имхо, читать JAML намного сложнее
                                                    0
                                                    Ну написал я зоопарк этих расширений. Кучу идей невозможно реализовать в принципе, потому что WPF окопался в MS.Internal. Например, у меня есть {AncestorBinding (TreeViewItem.PropertyName).PropertyPath}, который извлекает тип из первого свойства (оно задаётся в полной скобочной записи). И эта штуковина работает через отражения, потому что мелкомягкие закрыли метод, который позволяет определять тип по строке. DictionaryKeyPropertyAttribute не работает в принципе, он поддерживается только для встроенных типов. Потомка Setter с нормально прописанным ContentPropertyAttribute создать нельзя. И так далее, и тому подобное.
                                                      0
                                                      А зачем это все? Как на меня, но почти все трудности с XAML пропадают после установки Blend. Смотреть на XAML приходится не так часто.
                                                        0
                                                        Вы видели десктоповый Бленд для VS2012? Я — нет.

                                                        Да и всякие байндинги и прочую нечисть всё равно ручками писать. В шаблонах всякие монстры возникают постоянно.
                                                          0
                                                          Я видел Blend for Visual Studio 2012.
                                                          С багами он сейчас конечно, но вскоре поправят и нормальную версию и для десктопа сделают.

                                                          Вам вопрос тогда, а вам горит использовать VS2012 для десктоп приложений?
                                                            0
                                                            .NET 4.5: async, IDN, допиленный VirtualizingPanel. От этого отказаться невозможно, если уже попробовал.
                                                    0
                                                    XAML ещё очень удобен тем, что это простой XML, который можно легко парсить XPath, LINQ to XML. Несколько раз у меня была необходимость пропарсить все xaml'ы и поизменять кое-чего. Да та же локализация (см. мою статью про локализацию Win8).
                                                      0
                                                      Markup extension'ы как парсили?
                                                      • UFO just landed and posted this here
                                                      +3
                                                      Попахивает QML… I like it… :)
                                                        0
                                                        Странно, что народ спорит о читабельности XAML, но при этом никто не пытается оптимизировать аналогичным образом HTML.
                                                          +2
                                                          haml.info/
                                                          jade-lang.com/
                                                          slim-lang.com/
                                                          дада совсем никто.
                                                            0
                                                            Тут обсуждается изменение XML на аналог JSON при описании интерфейса, а не изменение управляющей разметки. Против аналогов Razor я ничего не имею против.
                                                          0
                                                          Чего-то как-то не в ту степь, имхо. Может я наловлю минусов, но меня XAML бесит вовсе не длинными выражениями, а низкой степенью интеграции со средой C#. Одно и то же описание на XAML и в коде выглядит ну абсолютно по-разному. Хотя зачем принципиально так сделано — мне непонятно. Более того, некоторое поведение практически невозможно реализовать из XAML, в итоге получается какой-то адский гибрид ужа с ежом.
                                                            0
                                                            XAML — декларативный язык, и было бы странно от него ожидать полнофункциональности C#, разве что путем поддержки скриптов, которые не способствуют читаемости, стабильности и отлаживаемости кода.
                                                            0
                                                            да нормальный XAML. У автора какие-то комплексы и видно, что куча времени свободного.
                                                              +1
                                                              Товарищ психотерапевт, вам топор точить некогда, лес рубить надо?
                                                                +1
                                                                Сравнение некоретное.
                                                                Топор хорошо наточен, инструменты разработки предоставлены, а вы сейчас пытаетесь из стручка и камня топор смастерить.
                                                              +1
                                                              Не понимаю возмущения громоздкостью XAML'а. Просто не надо весь код UI пихать в один файлик MainWindow.xaml и будет вам счастье. Выносите стили и часто повторяющийся код в отдельные ресурсы, декомпозируйте сложные контролы на более простые, в чем проблема?

                                                              Веб-разработчики пишут разметку в HTML, стили в CSS, логику в JavaScript, используют кучу библиотек, и ничего, как-то умудряются все это не помещать в одну кучу. Просто кто-то наигрался с JSON и ASP.NET MVC, и теперь их пугает избыточность XML. Эти данные же не по сети передаются, тут важнее читаемость и наглядность, чем компактность записи. «Избыточность» XAML служит устранению неоднозначностей, и это хорошо.
                                                                0
                                                                Не понимаю, почему все защищают наглядность XAML. Я не вижу наглядности в {Binding Path=Name, RelativeSource={RelativeSource AncestorType={x:Type Button}}, Converter={StaticResource Converter}}. Когда текста много, то это не только «наглядность», но и больше времени на прочтение кода, и меньше логики, умещающейся на одну страницу (мониторы пока не безразмерные). И когда я пишу <Setter.Value></Setter.Value>, я не устраняю каких-либо неоднозначностей, я вынужден писать эту конструкцию только из-за того, что разработчики забыли повесить на сеттер ContentPropertyAttribute.

                                                                Ну вот в C#, например, вы никогда не пользуетесь лямбдами, всегда только именованными методами? Вы всегда пишете foreach-if-List.Add вместо Select-Where-ToList? И то, и другое можно делать кратким способом, обвешанным синтаксическим сахаром, и длинным, традиционным. Каким способом вы пишете?

                                                                C# из всех строго типизированных компилируемых языков — один из самых удобренных синтаксическим сахаром, один из самых выразительных (это очень наглядно видно, например, при сравнении C# и Java). А вот в XAML этого всего нет.
                                                                0
                                                                есть куда более подходящий для этого формат — github.com/nin-jin/node-jin#tree
                                                                это логичеки xml но чуть больше свободы в именах и совсем без синтаксического мусора и даже без эскейпинга
                                                                может проще реализовать его на шарпе?

                                                                один из xml-примеров можно было бы переписать так:

                                                                Button
                                                                ....@ Visibility =Visible
                                                                ....Button.ToolTip
                                                                ........TextBlock @ Text =Tool tip text
                                                                ....TextBlock @ Text =Button text & 'another' «text»

                                                                вместо многоточий — табы
                                                                и так можно представить любой xml
                                                                  0
                                                                  Учитывая, что оно написано на JS, переписывать на C# будет очень невесело. Да и необходимость ровно одного символа отступа звучит несуразно. А так — выглядит как урезанный YAML.
                                                                +2
                                                                Здравствуйте, на данный момент я занимаюсь поддержкой XAML в ReSharper :)

                                                                Грустно, конечно, когда часть твоей работы оценивают как «сосёт и причмокивает»… Я присоединился к JB полтора года назад джуниором заниматься поддержкой XAML, которая на тот момент была, к большому сожалению, в достаточно заброшенном состоянии — поддержку написал один очень крутой человек и стал заниматься многими другими важными вещами, уделяя время багфиксам в XAML. Полгода я только въезжал что к чему в мире R#, а остальное время пытаюсь догнать все остальные подсистемы R#, починить критические баги, да ещё и фичи успеть новые сделать… Совсем переписал code completion в 7.1, портировал из web-поддержки всякие синхронные редактирования тегов и прочие typing assit фичи, сделал поддержку WinRT (вы не представляете сколько с ней было проблем, от проекций типов WinRT до правил приведений типов в XAML-дереве), сильно улучшил вывод типа контекста в биндингах (кстати оно было ещё до 6.0, там 1200 строк чистой магии) и многое другое. А ещё мне приходится проверять каждую фичу в WPF/SL/WP7/WinRT + иногда заглядывать в Workflow Foundation с XAML2009 :) Я очень надеюсь, что поддержка стала удобнее в 7.0/7.1 и мой труд заметен. Если вам, уважаемый топикстартер, по прежнему приходится иметь дело с XAML и R#, то милости прошу ко мне на огонёк. Планов на 8.0 прилично и мне будет приятно, если я смогу хоть немного исправить ваше отношение к нашей XAML-поддержке :)

                                                                Что до вашего языка — я думаю среди активных пользователей WPF оно действительно может востребовано; персонально не люблю JSON; конечный синтакис очень краткий — замечательно; языковые конструкции очень специфичные — когда-то я смог разобраться с XAML не читая спек и документации, с вашим языком это никак бы не прокатило (что за ~?).

                                                                Что до XAML — он ужасен и монструозен. Я был бы счастлив, если бы MS заменили его чем-нибудь легковесным или хотя бы уделяли развитию WPF больше внимания, потому что за те же 6 лет, за которые вы нас ругаете (у нас меньше лет поддержке на самом деле), MS вообще ничего кардинального с XAML не сделали.

                                                                Что до решения проблемы XAML — мне кажется куда проще напедалить достойный eDSL на обычном C#. Я видел в паре проектов такие, биндинги через Expression задаются (типизированные и рефакторятся — отлично), кучка extension-методов и уже куда удобнее XAML получается, лучше подвергается декомпозиции и т.п.

                                                                Что до поддержки новых языков в R# — у нас есть SDK, но мало документации, к сожалению. Недавно вышел плагин поддержки T4, его можно использовать как пример + можно связаться непосредственно со мной и я обязательно помогу чем смогу. Но я крайне сомневаюсь в том, что затея оправдает затраченные усилия, не в MS-стеке :)
                                                                  0
                                                                  На самом деле у меня претензия к поддержке XAML в Решарпере не столько в текущем состоянии, сколько в практически нулевом прогрессе все предшествующие годы. Если скорость разработки фич для замля сохранится такая же, как на отрезке 7.0-7.1 — это будет офигительно.

                                                                  В багтрекер я уже запостил один баг (рефакторинг переименования класса расширения разметки) и две фичи (атрибуты для свойств расширений разметки — под вдохновлением от поддержки на основании постфиксов; более детальное описание типов свойств — под вдохновлением от поддержки DataContext из Бленда). Как показал мой опрос из прошлого топика, финты ушами с расширениями разметки относительно популярны, так что, возможно, это окажется полезным не только для меня.

                                                                  Ну то есть да, прогресс заметен, спасибо. Хотя, если честно, на реализацию этих фич я особо не рассчитывал — как показывает опыт, в JetBrains запрос бесполезной фичи может быть реализован за пару дней, а критический баг с сотней голосов висеть по три года — чистая рулетка. :) Да и проблем с файлами XAML заметно больше: решарпер работает с ними медленно, рефакторинги глючат. Не знаю, имеет ли смысл репортить всё это.

                                                                  Насчёт тильды вы, пожалуй, правы. Наверное, логичнее заменить её на какой-нибудь всем понятный typeof — относительно невероятно монструозной записи через RelativeSource что угодно будет сокращением, на байтах можно не экономить. Но "=" для байндингов и "@" для ресурсов мне самому нравятся. Их часто приходится использовать в больших количествах и в сложных комбинациях, поэтому краткость оправдана.

                                                                  Есть какой-нибудь реальный проект записи XAML на C#? Можете кинуть ссылки? Мне видится несколько проблем:
                                                                  • Обращение к контролам по имени. В XAML требуется «объявить» элемент до первого к нему обращения. В fluent запись на C# объявления переменных засунуть не получится.
                                                                  • Пути в байндингах нетипизированные, тот же DataContext — типа object. Дженериков в WPF днём с огнём не сыщешь. Понадобится огромное колиство преобразований типов.
                                                                  • Однобуквенные сокращения типа "{=}" для байндинга станут невозможными.
                                                                  Это что первое в голову пришло. Вероятно, всплывут ещё проблемы.

                                                                  Надо будет глянуть на плагин Т4, как-то проглядел. Tangible ничего так, но хочется большего. :)
                                                                    +1
                                                                    Спасибо за реквесты, только что-то на меня некоторые не попали. Кастомные биндинги в 7.1 пришлось сделать костыльно через нейминг конвеншн, просто чтобы наконец они хоть как-то заработали, сделать полноценно через аннотации планируется в 8ке. Вообще резолв в маркап экстеншенах переписался полностью в 7.1, решило достаточно много проблем…

                                                                    Насчёт работает медленно — когда мне присылают снепшоты с «решарпер медленный в XAML», то в 95% там торчит студийные language service для XAML или XAML-дизайнер или код проекта в design-time тормозит. Абсолютному большинству помогает переключение типа редактора в VS на «Source code», жертвуя дизайнером. Для XML у нас очень и очень быстрый рукописный парсер, в 7.1 для комплишена я сильно разогнал резолв (только первый раз после открытия проекта втыкает), так что если что-то реально втыкает, то лучше снять снепшотик — в 7.1 это делается в два клика ReSharper — Help — Profile VisualStudio, оно само аттачит ядро нашего dotTrace к студии, снимает снепшотик, само засылает на наш FTP.

                                                                    XAML на C# видел в проекте кастомера, у меня его нет и показать бы не смог. Именования разруливались как-то типа var nameReference = button.WithName(«Foo»); и дальше использовался тип-референса на имя. В каждом биндинге аннотировался тип DataContext'а, насколько я помню.
                                                                  0
                                                                  Думается мне, что реализация в форме runtime-библиотеки нецелесообразна. Сложная адаптация существующего кода, модификация типа проекта, build action'ы, парсер и кодогенератор. Всё это довольно приличный объем работы, и я бы сказал избыточный. Лично я бы решал основною проблему — неудобство чтения и написания XAML. XAML хорошо компилируется и выполняет свою, задачу а вот читать и редактировать его очень неудобно.
                                                                  Поэтому самое простое и эффективное решение — конвертер XAML<->JAML «на лету». Что я предлагаю сделать.
                                                                  Структура проекта не меняется. В студию добавляется расширение, которое добавляет новый редактор для XAML файлов. Открывая их вы видите уже JAML, и его же редактируете. При сохранении файла обновляется XAML.
                                                                  Тут объем задач значительно меньше, и реализация мне видится значительно более реалистичной. И я бы на самом деле пошел бы еще дальше. Зачем текст, если можно сделать структурированный редактор? Ведь XAML это дерево. Так я бы и сделал дерево, что бы можно было в узлах печатать текст. При этом не нужно замарачиваться с отступами, форматированием. К тому же исчезнет эта жуткая каша из стилей и шаблонов в больших файлах. Проще сделать code completion, уже будет folding. Если узел сделать не текстовым, а «наборным», что бы контент узла можно было бы формировать спец редакторами (выпадающими списками, up-down'ами и т.д., на подобии редактора правил в каком-то файрволе, типа — «Где протокол: {x}, и направление {y}, то {запретить/разрешить}»), то отпадает необходимость в парсере, можно будет просто использовать объектную модель документа.
                                                                  В студии, к слову, Cider (тот самый глючный редактор), построен по похожему принципу, и там есть объектная модель документа и дизайнер и редактор кода связаны с ней. Таким образом удаляя элемент в дизайнере вы удаляете текст и наоборот. Если удастся к ней прицепиться, то можно будет даже добиться автоматической синхронизации свойств в PropertyGrid'е и в «деревянном» редакторе.
                                                                    0
                                                                    Думается мне, что реализация в форме runtime-библиотеки нецелесообразна. Сложная адаптация существующего кода, модификация типа проекта, build action'ы, парсер и кодогенератор. Всё это довольно приличный объем работы, и я бы сказал избыточный.

                                                                    Не-не-не, здесь как раз всё минималистично, хотя и с некоторым упором на удобство разработки библиотеки, а не удобство её пользователя. В рантайме библиотека не нужна. Тип проекта (?) не модифицируется. Используется Custom Tool (то, что в редакторе вызывается для генерации файла(ов) при сохранении исходника), а не Build Action (то, что влияет на способ засовывания файла в исполняемый файл). В исполняемом файле будет всё тот же XAML, скомпилированный в BAML. JAML существует только в проекте и только для генерации XAML и CS файлов.

                                                                    Сейчас между JAML и XAML лежит прослойка из T4, но она легко скрывается в тривиальной реализации интерфейса ISingleFileЧегоТоТамПреобразователь. Можно зарегать новый тип файла в сутдии. Создал JAML — под ним сразу появились сгенерированные файлы. Проблема в том, что в этом случае сборка библиотеки намертво присобачивается к студии, и пересобрать её можно только после перезапуска. Промежуточный слой с T4 решает эту проблему, потому что T4 загружает теневые копии сборок — пересобирай и перезапускай сколько душе угодно. Так что это исключительно вопрос удобства разработки.

                                                                    В студию добавляется расширение, которое добавляет новый редактор для XAML файлов. Открывая их вы видите уже JAML, и его же редактируете.

                                                                    Идея в целом мне нравится, но мне видится две проблемы.

                                                                    Во-первых, не уверен, что такое можно нормально реализовать. Я видел плагины двух типов: которые используют встроенный редактор студии и добавляют подсветку и/или автодополнение кода; и которые вставляют вместо студийного поля ввода свой собственный велосипед, в котором, разумеется, не работает половина студийных фич. Архитектурно верным мне видится первый способ, потому что не заставляет разработчика использовать непонятно что с непонятно какими сочетаниями клавиш. Так вот, не уверен, что можно реализовать первым способом эту идею с подменой файла.

                                                                    Во-вторых, в реализацию полноценного автодоплнения кода и валидации своего языка я верю с трудом, поэтому заглядывать в XAML всё-таки придётся. Если скрыть внутренность файла от юзера, то проверять нагенеренное будет очень неудобно.

                                                                    Зачем текст, если можно сделать структурированный редактор? Ведь XAML это дерево. Так я бы и сделал дерево, что бы можно было в узлах печатать текст. При этом не нужно замарачиваться с отступами, форматированием.

                                                                    Не видел ни одного вменяемого «визуального редактора» XML, которым было бы удобно пользоваться. Да и байндинги галками описывать — это как? :)
                                                                    0
                                                                    То, что XAML — индусский франкенштейн — однозначно, «хочется взять и упереписать!». Навскидку, у него три беды:
                                                                    1. Излишние закрывающие теги (какого чёрта не воспользоваться </>? )
                                                                    2. Невозможно задать сложное значение атрибуту — приходится делать вложенные теги, что не прибавляет читабельности.
                                                                    3. Язык привязки абсолютно гетерогенен основному языку разметки — что-то вроде JSON внутри XML.

                                                                    Но главная попаболь XAML — это априори ущербная крайняя позиция: «если всё не процедурное, значит всё декларативное!». Именно это сыграло злую шутку, превратив изначально шикарную идею в маразм. На XML взвалили слишком много, отчего даже по природе процедурные вещи стали писаться декларативно, причём в 10 раз больше кода.

                                                                    Решение с JSON меняет профиль кода, но он не становится сильно читабельнее — JSON (при своей иерархичной природе) не умеет «красиво» представлять узлы — фактически, он только показывает вложенность. Вот вариант языка разметки на подумать:

                                                                    [Button Text=«click me!» OnClick={ MessageBox.Show(«Ишь, чего захотел!»); }]
                                                                    [DockPanel
                                                                    [Label dock=«left» Layout=«ImageAboveText»
                                                                    [Image src=«smile.gif»]Метка с иконкой
                                                                    ]
                                                                    [TextBox Width=«200»]
                                                                    ]

                                                                    Идеальным решением мне видится декларативный подход как у XAML, но урезанный до той степени, когда написать код — проще, чем связываться с декларациями. А уж создать контрол и прицепить пару хэндлеров куда проще, чем изгаляться с многостраничными иерархиями непойми чего в шаблонах. Другими словами, если «тюнинг» контрола становится слишком сложный, это значит либо неправильный контрол, либо тебе нужен новый контрол, требующий минимум доводки.

                                                                    Only users with full accounts can post comments. Log in, please.