Релиз кросс-платформенного .NET UI-тулкита AvaloniaUI 0.9

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Avalonia — кроссплатформенный .NET UI-тулкит с открытым исходным кодом, вдохновлённый технологиями WPF и UWP. Он полностью поддерживает Windows, macOS и Linux, .NET Core 2.0-3.1, XAML, дата-биндинги, lookless-контролы и многое другое.



(на ВДПВ показана работа без XOrg)


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


За подробностями прошу под кат.


Компилируемый XAML


В прошлых версиях парсинг XAML происходил во время выполнения приложения. Этот подход имел ряд недостатков:


  • медленно
  • программа компилируется без ошибок, а потом не работает (QML, я смотрю на тебя)
  • используемый парсер выдавал невразумительные ошибки типа "The value of 'Content' property is null" при опечатке в названии контрола.

Наш новый компилятор всё парсит во время компиляции и перегоняет прямо в MSIL. Можно даже посмотреть на хелловорлд декомпилятором и увидеть что-то типа этого:


Декомпилятор, кстати, тоже работает на авалонии.


За счёт этого получилось выкинуть уйму обращений к рефлексии, за счёт чего запуск приложения стал турбореактивным. Только наш каталог контролов после перехода на компилятор стал запускаться на 40% быстрее.


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



Глобальные меню в macOS и Linux


На маках приложения меню внутри окна обычно не рисуют, поскольку наверху экрана есть глобальная строка меню для всех. На ряде десктопных окружений Linux (Unity, KDE с поставленной галкой в настройках, vala-panel-appmenu) так же доступна схожая возможность.


В Avalonia появилась поддержка таких меню, в коде выглядят они примерно так:


<Window>
  <NativeMenu.Menu>
    <NativeMenu>
      <NativeMenuItem Header="File">
        <NativeMenuItem.Menu>
          <NativeMenu>
            <NativeMenuItem Header="Open" Command="{Binding OpenCommand}"/>
            <NativeMenuItemSeperator/>
            <NativeMenuItem Header="Recent">
              <NativeMenuItem.Menu>
                <NativeMenu/>
              </NativeMenuItem.Menu>
            </NativeMenuItem>
            <NativeMenuItemSeperator/>
            <NativeMenuItem Header="Quit Avalonia" Command="{Binding CloseCommand}" Gesture="CMD+Q"/>
          </NativeMenu>
        </NativeMenuItem.Menu>
      </NativeMenuItem>
      <NativeMenuItem Header="Edit">
        <NativeMenuItem.Menu>
          <NativeMenu>
            <NativeMenuItem Header="Copy"/>
            <NativeMenuItem Header="Paste"/>
          </NativeMenu>
        </NativeMenuItem.Menu>
      </NativeMenuItem>
    </NativeMenu>
  </NativeMenu.Menu>
</Window>

Не пугайтесь CMD+Q, оно на не-маке смаппится на `Control+Q. Это теперь такой синоним для платформозависимого модификатора "Command".


Чтобы людям не заниматься копипастой такой же структуры в "обычное" меню для "традиционных" платформ мы так же завезли контрол <NativeMenuBar/>, который можно положить туда, где это самое меню должно быть. Ну а контрол уже сам заберёт все этим NativeMenu и сам разберётся, надо ли его рисовать или система справится.



меню окна в глобальном баре на макоси


Так же на macOS есть особенность — у приложения есть пункт меню с именем приложения. Там обычно находятся элементы, глобальные для всего приложения типа настроек. Мы, чтобы пользователи не удивлялись, это меню генерируем по-умолчанию:

дефолтное содержание меню приложения


Ну а кастомизировать его надо в вашем App.xaml:


<Application>
  <NativeMenu.Menu>
    <NativeMenu>
      <NativeMenuItem Header="About MyApp" Command="{Binding AboutCommand}" />
    </NativeMenu>
  </NativeMenu.Menu>
</Application>

Соответственно, у Application теперь есть свой собственный DataContext, в который можно положить вьюмодель. Ну чтобы было куда биндиться.


На Linux, ввиду его общей, кхм, разнородности, данная опция по-умолчанию выключена и может быть включена посредством:


.With(new X11PlatformOptions
{
    UseDBusMenu = true
})

Я лично тестировал на Unity и в KDE на Ubuntu 18.04, но кто ж его знает, как оно в других дистрах.


Managed-реализации файловых диалогов


Если по каким-то причинам не хочется использовать нативные диалоги (например, не хочется тащить в embedded-систему цельнотянутый GTK), теперь можно воспользоваться реализованными на самой авалонии:



Весь API тот же самый, просто надо включить в AppBuilder-е:


AppBuilder.Configure<App>()
.UsePlatformDetect()
.UseManagedSystemDialogs();

Если хочется положить диалоги в кастомное окно (рамочку там свою нарисовать, например, цвета застилизовать), то делается это так:


.UseManagedSystemDialogs<AppBuilder, MyCustomWindowType>();

ItemsRepeater


Из UWP был портирован ItemsRepeater. Данный контрол позволяет делать высокопроизводительные виртуализированные списки с элементами разных размеров и плавной прокруткой. Layout при этом контролируется отдельно от контрола посредством системы Attached Layouts.


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


Импорт Grid and GridSplitter из WPF


Продолжаем портировать контролы из теперь-уже-почти-скоро-может-быть-целиком-совсем-совсем-опенсорсного WPF. Из уже опенсорсных его частей.


В этот раз перетащили такую фундаментальную штуку как Grid, вместе со всеми его SharedSizeGroup-ами и GridSplitter-ом. Так что теперь тот код, что работал в WPF будет работать в авалонии так же, а не "вообще так же, но ...".


Оптимизации производительности


Над ними произведена большая работа. В основном по выкорчёвыванию LINQ отовсюду и ненужных аллокаций из самых неожиданных мест. Так что на Raspberry Pi у нас теперь анимации выдают FPS, а не SPF.


KMS/DRM/GBM/libinput на линуксе


То, что показано на видео перед катом. Мы теперь умеем использовать ту же самую инфраструктуру, на базе которой работают новые более лучшие дисплейные менеджеры, которые понемногу приходят на замену Xorg. Что позволяет нам работать без дисплейного менеджера вообще, прямо поверх линуксового ядра да ещё и с аппаратным ускорением через OpenGL.


Эта функция даёт вам возможность делать системы-"киоски", в которых запущен только ядро Linux и ваше приложение.


Поддержка сенсорного ввода


Пока что выключена по-умолчанию, но при наличии сенсорного экрана может быть включена через добавление следующего кода в ваш AppBuilder:


.With(new X11PlatformOptions
{
    EnableMultiTouch = true
})
.With(new Win32PlatformOptions
{
    EnableMultitouch = true
})

Если раньше сенсорный ввод обрабатывался как эмулируемая операционной системой мышь, то теперь мы перешли на UWPшную модель pointer events с отдельным "указателем" на каждый контакт с сенсорной поверхностью. Так же завезли базовую поддержку распознавателей жестов, на которой сделали поддержку скроллинга пальцем.


Весенние видео с первыми демонстрациями:




Production Ready


У нас постоянно спрашивают "а пригодно ли для продакшна?", "а когда 1.0?". Да, пригодно. 1.0 будет, согласно модели SemVer, когда перестанем каждую версию по чуть-чуть менять API (ну или можем перейти на браузерную модель версионирования и через пару лет будет "состоялся релиз AvaloniaUI 71").


В настоящий момент есть несколько приложений на AvaloniaUI с большими пользовательскими базами. Мы знаем о ряде коммерческих приложений, портируемых на AvaloniaUI. Командам всех этих проектов мы хотим сказать спасибо за неоценимую помощь в тестировании этого релиза.


Ввиду подобного активного использования, мы переходим на новую модель поддержки релизов. Ветка 0.9 будет поддерживаться багфиксами и бекпортированием критических изменений вплоть до выхода следующей версии.
Так же со следующего года будет доступна техническая поддержка на коммерческой основе. Это не потому, что мы жадные, это потому, что на энтузиазме и "в свободное после работы время" далеко не уедешь и нужны разработчики на full-time. Условия пока вырабатываются, что если вам интересно или есть что-то срочное, то пишите на team@avaloniaui.net


Как начать пользоваться


Есть достаточно подробный туториал на английском. Для знакомых с WPF/UWP разработчиков всё должно быть интуитивно и просто, есть перечень наиболее важных отличий.


Благодарности


Этот релиз стал возможен благодаря работе многих людей, в частности grokys, jkoritzinsky, kekekeks, danwalmsley, jmacato, marchingcube, wieslawsoltes, gillibald и многих других.


Лучший способ поддержать Avalonia — принять участие в разработке: реализовать фичу, починить баг или помочь в тестировании. См. страницу Contributing

Источник: https://habr.com/ru/post/481102/


Интересные статьи

Интересные статьи

С тех пор как Windows Forms был «Open Soursed» в конце 2018 года и в целом интерфейс был перенесен на .NET Core, и команда, и наши внешние участники были заняты исправлением старых ошибок...
rotor — ненавязчивый С++ акторный микрофремворк, похожий на своих старших братьев — caf и sobjectizer. В новом релизе внутреннее ядро полностью было переделано с помощью механизмов ...
Один из ключевых сценариев работы в CRM это общение с клиентом в удобном для него канале. По почте, по телефону, по SMS или в мессенджере. Особенно выделяется WhatsApp — интеграцию с ...
Появление async/await в C# привело к пересмотру того, как писать простой и корректный параллельный код. Зачастую, используя асинхронное программирование, программисты не только не решают проблемы...
Практически все коммерческие интернет-ресурсы создаются на уникальных платформах соответствующего типа. Среди них наибольшее распространение получил Битрикс24.