В первую очередь установим необходимый шаблон.
Для этого сохраняем этот репозиторий на свой машине.
Открываем консоль и пишем:
dotnet new --install [путь до скачанного шаблона]
И создадим стартовый проект:
dotnet new avalonia.mvvm -o Notebook
Добавим простенькую разметку как в wpf в файле MainWindow.xaml.
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:Notebook.ViewModels;assembly=Notebook"
Icon="resm:Notebook.Assets.avalonia-logo.ico"
Title="Notebook">
<!--Биндим горячие клавиши-->
<Window.KeyBindings>
<KeyBinding Gesture="Ctrl+O" Command="{Binding Open}" />
<KeyBinding Gesture="Ctrl+S" Command="{Binding Save}" />
</Window.KeyBindings>
<Design.DataContext>
<vm:MainWindowViewModel />
</Design.DataContext>
<!--Стандартная разметочка гридом-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!--Менюшечка-->
<Menu Grid.Row="0" Grid.Column="0">
<MenuItem Header="File">
<MenuItem Header="Open" Command="{Binding Open}" />
<MenuItem Header="Save As" Command="{Binding Save}" />
</MenuItem>
</Menu>
<!--Основное текстовое поле-->
<TextBox Grid.Row="1" Grid.Column="0" Text="{Binding Data}"
AcceptsReturn="True" />
</Grid>
</Window>
C mvvm тут все чуть по-другому, так как по дефолту используется ReactiveUI.
Так что в файле MainWindowViewModel.cs добавим:
private string _data;
public string Data
{
get => _data;
set => this.RaiseAndSetIfChanged(ref _data, value);
}
А вот в отличии от дефолта wpf, авалония позволяет биндить комманды напрямую к методам.
И так же стоит отметить, что файловые диалоги в данном фреймворке только асинхронные.
Тогда открытие документа будет выглядеть вот так:
public async Task Open()
{
var dialog = new OpenFileDialog();
string[] result = null;
dialog.Filters.Add(new FileDialogFilter() {Name = "Text", Extensions = {"txt"}});
result = await dialog.ShowAsync();
if (result != null)
{
Data = File.ReadAllText(result.First());
}
}
А вот так сохранение:
public async Task Save()
{
var dialog = new SaveFileDialog();
dialog.Filters.Add(new FileDialogFilter()
{Name = "Text", Extensions = {"txt"}});
var result = await dialog.ShowAsync(new MainWindow());
if (result != null)
{
File.WriteAllText(result, Data);
}
}
Для того, что бы приложение запускалось на Линуксе придется добавить еще одну зависимость: Avalonia.Skia.Linux.Natives.
Но к сожалению не все сборки смогут отобразить наше окно. Ubuntu ( в том числе и Mate) отлично справляется как на большой (x64) архитектуре, так и на arm, а вот Raspbian явно подводит.
P.S.
Проект безумно интересный и приятный. Имеет очень много таргетных платформ в том числе и яблочных, надеемся, что скоро он будет отлично работать на всех платформах.
Комментарии (13)
samodum
05.02.2019 03:37+1Может, надо начать с того, чтобы рассказать, что это вообще такое этот ваш AvaloniaUI, для чего он нужен и какие задачи решает?
А то вылили на нас ушат с этим кодом и что нам с ним делать?Larymar Автор
05.02.2019 03:40там вроде бы сказано
корссплатформенным GUI Framework
Что еще он может решать, кроме кроссплатформенного отображения окон)
petuhov_k
05.02.2019 07:09Классная штука, эта Avalonia, жаль, что сырая и, когда доварится, не известно.
Сам пробовал, портировать несложное приложение с UWP. В целом заработало, даже избавился от некоторых костылей. Но, есть и бочка дёгтя. Под Android запускается только Debug версия, при этом тормозит нещадно, реакция на действия десятки секунд. Под убунтой упомянутые файловые диалоги не открываются. А разработчики, похоже, сосредоточились на iOS. Жаль.kekekeks
05.02.2019 07:52+1С диалогами был некоторый просчёт в проектировании API, когда буквально все требовали "как в WPF", ибо "на винде работает же". В итоге по дефолту ShowDialog не принимал родительского окна, что вызывало ряд спецэффектов с линуксовыми оконными менеджерами, имеющими особое мнение о том, где и как надо показывать свежепоявившиеся окна. Особенно странностями страдает третьегномовский Mutter, который окно может не показать вообще, ибо у GTKшного файлодиалога выставлен
_NET_WM_STATE_SKIP_TASKBAR
. Усугублялось это тем, что тестировалось всё обычно на Ubuntu+Unity, а Compiz подобной самодеятельностью не страдает, и всё работало.
Сейчас все диалоги в обязательном порядке требуют наличия родительского окна.
В общем, линуксозоопарк десктопных, о ряде особенностей которых можно узнать только по багрепортам. Особый смак — когда проблемы очередного WM не проявляются при запуске оного под Xephyr (приходится запускать отдельную сессию), либо дистрибутивозависимы (приходится запускать виртуалку, а там обычно ещё и llvmpipe в качестве драйвера), либо дистрибутиво- и драйверозависимы (проще повеситься). Как
optirun
ломаетdlsym(dlopen("libdl.so.2", RTLD_NOW), "dlsym")
, что делает невозможным использованиеdlsym
через[DllImport]
— вообще отдельная история.
Ещё имели кучу проблем с патчеными версиями GTK (привет, ElementalyOS), из-за которых ничего не работало. Сейчас, вроде, осилили бакэнд, работающий напрямую с libX11 и с GLX, стало немного полегче.
petuhov_k
05.02.2019 08:12Никита, Вы есть крут. Ваш комментарий тянет на отдельную статью на хабре. Но, чёрт с ними, с диалогами. Ясно, что вызов нативного окна в произвольной ОС — задача неблагодарная. Меня больше волнует Android, что с ним?
kekekeks
05.02.2019 08:24Примерно то же самое, что и с iOS — сделали экспериментальные бакэнды, чтобы понять, где лежат грабли, и какие вообще у платформ ограничения, после чего сосредоточились на самом фреймворке и поддержке десктопа. Вот тут я с месяц назад расписывал, чего не хватает для нормальной работы на мобилках.
С андройдом в частности главная проблема в том, что на нём очень много low-end девайсов, а моновский AOT-компилятор под эту платформу далеко не так хорош, как под iOS. Отсюда тормоза. А если по каким-то причинам OpenGLES не заведётся, будет совсем грустно (сейчас вот он там у нас после миграции на SkiaSharp выключен, например).
Я сейчас потихоньку делаю компилятор XAML в MSIL, что должно снять хотя бы часть проблем со временем загрузки, но в целом нормальную поддержку мобилок раньше конца года ожидать не стоит.
VeroLom
05.02.2019 12:37Может, я не очень в теме, но что мешает использовать те же Gtk/Qt/Wx? Биндинги под шарп есть.
kekekeks
05.02.2019 18:31+1GTK уже научился в per-monitor DPI на X11? У них же иксы теперь "устарели" и все силы брошены на новый более лучший дисплейный сервер. Да и отрисовку из не-UI потока нормально не сделать.
В целом же "мешает" ими пользоваться неимоверная боль при попытке написать что-то сложнее хелловорлда привыкнув к XAML-фреймворкам, где есть нормальная человеческая поддержка MVVM.
Моя прошлая попытка изготовить что-то на GTK# закончилась переписыванием на C++/QtWebkit/JS (электрона в те годы не было)
nevdokimof
06.02.2019 01:42Avalonia — крутая штука, единственная беда — очень не хватает хорошей документации, местами вообще провалы.
John_Minority
Что это?
Imbecile
MS так и не сподобился сделать кроссплатформенный UI Framework. И Xamarin — его покупка — решила проблему отчасти, ибо не умеет в Linux. И сейчас, если хочется .NET и единый UI вообще на всём, то выбирать приходится Avalonia. Open source и очень кроссплатформено, но пока что с багами.
zartarn
Вопрос помоему не к тому, что такое авалония, а к тому о чем статья. ничего же нет. Про авалонию тут на забре и так есть куда более содержательные статьи, а не этот очерк.