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
Комментарии (20)
Siemargl
19.12.2019 11:25Над ними произведена большая работа. В основном по выкорчёвыванию LINQ отовсюду и ненужных аллокаций из самых неожиданных мест.
Неужели кто то в настоящем времени что то делает и руками! =)
KvanTTT
19.12.2019 13:53Так же со следующего года будет доступна техническая поддержка на коммерческой основе.
Для начала можно потратить сумму, накопленную на https://opencollective.com/avalonia По ней есть какие-нибудь планы? :)
kekekeks Автор
19.12.2019 14:39+1Вообще планировали эту сумму потратить на:
1) писателя документации
2) сайт
Тут суть в том, что не вполне корректно тратить деньги с опенколлектива на нужды коммерческой конторы. Поэтому вот так вот.
Sing
19.12.2019 14:26+2Скажите, есть ли какие-то обращения к вам от Microsoft? Может быть, по приобретению или спонсорству.
Если да, то какой прогресс? Если нет, то хотели бы, или будете независимыми до конца? )
На фоне приобретения Xamarin, движению к кроссплатформе и опенсурсу, а также поддержки Mono, странно что вас в упор не замечают.beskaravaev
19.12.2019 15:53+1Майки к опенсорсу двигаются весьма условно и преследуют определённые интересы. Core кросплатформенный, чтобы сервисы написанные на нём можно было запускать на виртуальных машинах Linux на их Azure. Так же и с мобилками, если у вас есть приложение, то для него почти наверняка нужен сервер и тут опять же Azure, а если не нужен, то оно наверняка маленькое и всем на него пофиг. Т.е. они таким образом укрепляют свои позиции в предоставлении облачных вычислений. А GUI в Linux им не нужен и его там не будет, во всяком случае официально, поэтому вся надежда на AvaloniaUI.
kekekeks Автор
19.12.2019 15:56+1Собственно, это хорошо видно на примере MonoDevelop. В нём сначала поддержку отладки .NET Core вырезали по лицензионным соображениям, а потом так вообще даже на сборку в Linux (и Windows) забили, теперь только под macOS.
Хочешь разрабатывать из под линукса — бери чудесный кроссплатформенный блокнот с автокомплитом, которого хватает ровно на написание микросервиса под ASP.NET Core, а ничего другого тебе под линуксом и не надо.
Tantrido
19.12.2019 17:47Молодцы! Ещё книжку надо, чтобы 2 было: Троелсен + книга по Авалонии :) И порядок с кросс-платформенностью у .Net. Кстати у вас только WPF/UWP совместимость или WinForms тоже есть?
kekekeks Автор
19.12.2019 17:48"Совместимости" нет, есть интеграция. То есть, встройка контролов на авалонии в WPF и в WinForms.
kefirr
20.12.2019 21:00Очень круто, особенно впечатлила компиляция XAML и ходьба по нему в дебаггере!
А где взять и запустить "каталог контролов"? Что-то с ходу не нашел.
MonkAlex
20.12.2019 21:15github.com/AvaloniaUI/Avalonia/tree/master/samples/ControlCatalog.Desktop
В сэмплах, собирать с сорцов видимо только. Ну, я собираю с сорцов, когда хочу потыкать.KvanTTT
21.12.2019 22:05Вообще у них есть билд-система https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build, и я оттуда раньше артефакты скачивал. Сейчас почему-то недоступно.
kekekeks Автор
22.12.2019 18:02https://github.com/AvaloniaUI/ControlCatalogStandalone — отдельнолежащий. Запускать через
dotnet run
kreo_OL
21.12.2019 20:54Я наверное не впопад и без теорбазы, но мобилки не планируется в дальнейшем поддерживать?)
MonkAlex
21.12.2019 20:58github.com/AvaloniaUI/Avalonia/issues/2239
Кратко — когда-то будет, прям щас оно не особо юзабельно на мобилках.
kekekeks Автор
22.12.2019 18:01Вообще планируется, но сейчас для нормального порта в основном фреймворке не хватает инфраструктуры для поддержки не западноевропейскоклавиатурных методов ввода. Ну там всякие китайские письменности и прочее. Как ни странно, привычные всем фишечки типа автодополнения и автокоррекции сделаны на базе той же самой инфраструктуры и подходов.
MonkAlex
С релизом.
Скорость работы приложения выросла заметно, что очень приятно.
Буду в ближайшее время мучать новое меню в Маке и посмотрю в линуксах, крутая фича, спасибо =)