Состоялся релиз первой бета-версии Авалонии.
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#1086ReactiveUI обновлён до восьмой версии#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.
