Состоялся релиз первой бета-версии Авалонии.
Avalonia — кроссплатформенный .NET UI-тулкит, вдохновлённый технологиями WPF и распространяемый под лицензией MIT. Он полностью поддерживает .NET Core 2.0, XAML, дата-биндинги, lookless-контролы и многое другое. Avalonia позволяет писать на C# приложения под Windows, Linux и Mac OS X. Возможность запуска на iOS и Android находится в экспериментальном состоянии.
Данная версия стабильна и имеет полное право называться бетой: тулкит не разваливается в руках и имеет приличный базовый набор контролов (см. видео). На нём создано два достаточно больших приложения с открытым исходным кодом: AvalonStudio — кроссплатформенная IDE для разработки на C# и C++ и Core2D — редактор 2D-схем и диаграмм.
Самый простой способ взять и начать пользоваться — установить наше расширение для Visual Studio или же воспользоваться шаблонами для dotnet new. Для ознакомления доступны примеры в основном репозитории.
В процессе подготовки релиза произошёл ряд важных изменений:
- Переход на платформу .NET Standard 2.0
- Старый медленный XAML-парсер заменён на Portable.Xaml, что позволило ускорить запуск AvalonStudio с 25 до 7 секунд (на SSD или на HDD с "горячим" файловым кэшем).
- Удалены старые и несовместимые с .NET Core бэкенды Cairo и gtk-sharp. Вместо них теперь используется Skia (библиотека отрисовки 2D из состава Google Chrome) и собственные биндинги к GTK3.
- Вместо форка ReactiveUI 8 перешли на официальную версию, поскольку она стала поддерживать .NET Standard.
- Запущен сайт avaloniaui.net, на котором доступна документация. В будущем там будут добавлены статьи.
Основные возможности в релизе
Retained-режим отрисовки в отдельном потоке
Раньше окно полностью перерисовывалось при каждом изменении. Этот подход прост и надежен, но крайне неэффективен. Вместо него был реализован DeferredRenderer
, который преобразует вызовы нашего API отрисовки в граф сцены окна. Отдельный поток ищет в графе измененные участки и перерисовывает только их. Помимо снятия нагрузки с UI-потока это позволяет добавлять оптимизации, выделяя части окна в кешируемые слои.
Новая инфраструктура рендеринга ощутимо улучшила производительность, особенно в случаях с анимациями. Так же это дало нам возможность реализовать нормально работающий hit-testing.
Если у вас возникают проблемы при использовании новой инфраструктуры, старая реализация ImmediateRenderer
оставлена для совместимости.
MonoMac-бакэнд для OS X
Поскольку GTK2/GTK3 — тяжелые библиотеки (~60MB), а использовались только ради обертки над нативным Carbon API, мы реализовали Cocoa-бэкенд с помощью специально собранного под .NET Standard MonoMac. Это упростило сборку бандлов и позволило использовать родные для OS X файловые диалоги вместо "универсальных", предоставляемых GTK.
Синтаксический сахар для RelativeSource
Ранее, как и в WPF, привязки к другим контролам осуществлялись через RelativeSource
. Этот синтаксис очень многословен: например, привязка текста на свойство Tag
родительского элемента выглядит примерно так:
<Border Tag="Hello World">
<TextBlock Text="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Border} AncestorLevel=1}}"/>
</Border>
Новый синтаксис позволяет переписать это вот так:
<Border Tag="Hello World">
<TextBlock Text="{Binding $parent.Tag}"/>
</Border>
Помимо ключевого слова $parent
добавлены следующие возможности:
Сокращение | Полная форма |
---|---|
$self |
Mode = Self |
$parent |
Mode = FindAncestor; AncestorLevel = 1 |
$parent[Level] |
Mode = FindAncestor; AncestorLevel = Level +1 |
$parent[ns:Type] |
Mode = FindAncestor; AncestorType = ns:Type |
$parent[ns:Type; Level] |
Mode = FindAncestor; AncestorType = ns:Type; AncestorLevel = Level + 1 |
*ns:Type
— неймспейс: Тип, например Border
или local:MyControl
Drawing
Drawing
— удобное представление для векторной графики типа иконок, используемое в WPF. Библиотека изображений Visual Studio предоставляет сотни иконок в данном формате. Их использование улучшает производительность, поскольку все части изображения являются одним элементом visual tree.
Теперь в Avalonia появилась поддержка данного формата. Наш стандартный контрол Image
пока не умеет с ними работать, но вы уже можете использовать DrawingPresenter
.
StaticResource
и DynamicResource
В новой версии добавлены привычные по WPF/UWP Control.Resources
, StaticResource
и DynamicResource
.
Реализация в точности соответствует аналогичному функционалу в WPF/UWP. Раннее все ресурсы были привязаны к стилям и для доступа к ним предлагалось использовать {StyleResource}
. Теперь у каждого элемента управления есть свой словарь ресурсов, которые наследуются по дереву элементов. Расширение разметки {StyleResource}
было удалено: теперь вместо него следует использовать {DynamicResource}
.
Привязка команд к методам
Думаю, у всех есть в проекте реализация ICommand
, принимающая в конструкторе делегат. Чтобы не плодить лишние сущности, привязка напрямую к методам вью-модели добавлена в сам фреймворк.
public class ViewModel
{
public void ButtonClicked()
{
Console.WriteLine("Hooray!");
}
}
<Button Command="{Binding ButtonClicked}"/>
Календарик
Был утащен из Silverlight Toolkit. Теперь можно выбирать даты.
Интеграция с WPF
В новой версии компоненты Авалонии можно полностью бесшовно встраивать в приложения на WPF. Это стало возможным за счет того, что системы layout-а в Авалонии и WPF практически идентичны, а Direct2D с помощью чёрной магии может рендерить прямо в заточенный под Direct3D 9 D3DBitmap
. Демку можно посмотреть тут.
Любопытно, что благодаря использованию Direct2D при такой интеграции на сложных сценах разница в производительности может достигать двух порядков в пользу Авалонии. Если у вас есть тормозящий контрол под WPF, может иметь смысл попробовать его портировать и встроить обратно.
Новая инфраструктура для превьювера с поддержкой .NET Core
Предыдущая версия предварительного просмотра для студии была написана за три дня со срезанием всех возможных углов. В результате она оказалась привязана к Win32 API, полному .NET Framework и Windows Forms. Теперь вместо неё была придумана более умная система, с общением по TCP/IP и возможностью передачи битмапов вместо прямой итеграции окна в Visual Studio. Это позволило нормально предпросматривать XAML в проектах под .NET Core и, что более важно, открыло дорогу для поддержки в других IDE. В частности, поддержка уже добавлена в AvalonStudio. Ведутся работы над плагином к Visual Studio Code, но это сложно: эта IDE построена на передовых и прогрессивных веб-технологиях и требует отдельный language-server, обвязку вокруг MSBuild и передачу картинок через WebSocket.
Помимо превьювера инфраструктура "удалённых" виджетов может пригодиться ещё где-нибудь, поэтому классы RemoteServer
и RemoteWidget
доступны для использования.
Иные улучшения
Полный список можно посмотреть тут, а ниже представлены самые интересные пункты:
#894
Кнопки выключаются, если привязка свойстваCommand
вернулаnull
#1085
ДобавленFindAncestor
#1086
ReactiveUI обновлён до восьмой версии#1128
У кнопки появилось свойствоIsPressed
#1133
Для всплывающей подсказки реализованыIsOpen
,Placement
,Offset
#1145
Переехали на .NET Standard 2.0#1146
Для окна реализовано свойствоShowTaskbarIcon
#1150
Реализовано API доступа к информации об экранах#1174
СожглиУбрали поддержку GTK2 and Cairo support#1175
РеализованныOrientation
иIsIndeterminate
у индикатора прогресса#1253
Для PageSlide-анимации реализована вертикальная ориентация#1265
Реализована поддержка трёх состояний дляToggleButton
,CheckBox
иRadioButton
(серенькое ни-да-ни-нет)#1273
Облегчили настройку логирования при настройке AppBuilder
Изменения, ломающие совместимость
Хорошая новость: мы их теперь отслеживаем и иногда даже документируем.
Плохая новость: они есть.
BuildAvaloniaApp
для превьювера.
Для работы новому превьюеру необходимо получить информацию у самого приложения. Для этого в классе с точкой входа (обычно Program.cs
прямо рядом с Main
) должен быть реализован метод BuildAvaloniaApp
, примерно такой:
static void Main(string[] args)
{
BuildAvaloniaApp().Start<MainWindow>();
}
public static AppBuilder BuildAvaloniaApp() =>
AppBuilder.Configure<App>()
.UsePlatformDetect()
.LogToDebug();
Без него предварительный просмотр работать не будет. Такие дела.
DataContextChanging
и DataContextChanged
Заменены на OnDataContextBeginUpdate
and OnDataContextEndUpdate
.
Расширения разметки Static
и Type
Заменены на x:Static
и x:Type
, нужно добавить пространство xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
в корневой элемент XAML-файла. Ибо стандартизация.
StyleResource
StyleResource
заменен на StaticResource
и DynamicResource
, как во всех нормальных XAML-фреймворках. StaticResource
и DynamicResource
ищут в Control.Resources
и Style.Resources
.
Mouse device
Убрали одну из глобальных переменных — MouseDevice
. Теперь мышь доступна на верхнем уровне: вызывайте GetVisualRoot
и приводите результат к IInputRoot
. Всё потому, что глобальные переменные и service locator — зло.
var pos = (_control.GetVisualRoot() as IInputRoot)?.MouseDevice?.Position ?? default(Point);
Как начать пользоваться?
Скачать дополнение к Студии и создать проект из шаблона. Полноценной документации пока нет, поэтому нужен опыт работы с WPF или UWP.