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

    Состоялся очередной бета-релиз AvaloniaUI.



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


    X11 backend для Linux


    Ранее для отрисовки окон под Linux мы использовали сначала GTK2, а затем GTK3. К сожалению от GTK было больше проблем, чем пользы, а вывод графики вообще приходилось делать через XPutImage с отдельного подключения к X-серверу.
    В #2011 был реализован работающий напрямую с libX11 backend, что помимо починки ряда багов и общего упрощения работы с окнами позволило реализовать поддержку per-monitor DPI, чего в GTK для X11 не делают по идеологическим соображениям вейландопревосходство (в Qt для X11 она есть).


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


    AvaloniaResource


    Ранее для ресурсов мы использовали EmbeddedResource, что приводило к именам ресурсов вида `resm:YourAssembly.Dir1.Dir2.file.xaml". Теперь мы реализовали MSBuild-таск, который позволяет ссылаться на ресурсы по нормальным Url как в WPF/UWP, а так же по относительным путям относительно текущего XAML-файла, например:


    <!-- на директорию выше -->
    <Image Source="../file.jpg"/>
    <!-- в /root/dir относительно корня проекта -->
    <Image Source="/root/dir/file.jpg"/>
    <!-- в /root/dir проекта "Assembly.Name" -->
    <Image Source="avares://Assembly.Name/root/dir/file.jpg"/>

    Для миграции старых проектов нужно заменить EmbeddedResource на AvaloniaResource, например:


    <AvaloniaResource Include="**\*.xaml">
      <SubType>Designer</SubType>
    </AvaloniaResource>
    <AvaloniaResource Include="Assets\*"/>

    Для привязки XAML-разметки к codebehind ранее использовалось сопоставление имени ресурса в EmbeddedResource с неймспейсом и именем класса, что доставляло ряд неудобств при несовпадении местоположения файла разметки имени и неймспейсу класса. Теперь для этого используется атрибут x:Class, как во всех XAML-фреймворках здорового человека:


    <UserControl xmlns="https://github.com/avaloniaui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 x:Class="MyApplication.MyUserControl">


    Тёмная тема


    В #2078 добавлена фича, которую все так долго ждали, тёмная тема.



    Примечание: табы слева стилизованы НЕ темой и в неё не входят


    Улучшение настройки платформозависимых опций


    Проведён некоторый рефакторинг конфигурирования платформозависимых опций. Ранее приходилось писать вот такую страшную портянку:


    public static AppBuilder BuildAvaloniaApp()
    {
        var builder = AppBuilder.Configure<App>();
        if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
             builder.UseX11(new X11PlatformOptions() {UseGpu = false});
        else if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
             builder.UseAvaloniaNative(anopts => 
             {
                  anopts.UseGpu = false;
                  anopts.MacOptions.ShowInDock = 0;
             });
        else if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
              builder.UseWin32(false, true);
        return builder;
    }

    Теперь всё кратко и красиво


    public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure<App>()
         .UsePlatformDetect()
         .With(new X11PlatformOptions { UseGpu = false })
         .With(new AvaloniaNativePlatformOptions { UseGpu = false })
         .With(new MacOSPlatformOptions { ShowInDock = false })
         .With(new Win32PlatformOptions { UseDeferredRendering = false });

    Обновлённый превьювер в плагине для Visual Studio


    Превьювер был переписан для использования передачи изображений по TCP. Ранее у нас был набор костылей с созданием внеэкранного окна и впихиванием оного в студию через user32!SetParent. Проблема с данным подходом была в том что он не всегда работал, а когда работал, не всегда как надо. Сейчас превьювер ведёт себя намного стабильнее.


    Так же в обновлённый плагин были внесены улучшения интелисенса


    ViewBox


    В #2066 был добавлен часто запрашиваемый контрол из WPF и UWP: ViewBox.


    DropDown переименован ComboBox


    Несмотря на то, что он таки дропдаун, а не комбобокс, мы его переименовали, чтобы было как у всех остальных (WPF/UWP). Старое имя пока ещё доступно, но будет удалено через пару релизов.


    DataGrid


    DataGrid теперь считается условно-готовым к использованию (ну просто потому что его уже активно используют), перенесён в главный репозиторий и опубликован в пакете Avalonia.Controls.DataGrid.


    Для использования нужно при конфигурировании приложения вызвать UseDataGrid:


    public static AppBuilder BuildAvaloniaApp()
         => AppBuilder.Configure<App>()
              .UsePlatformDetect()
              .UseDataGrid();

    и прописать его дефолтную тему в App.xaml:


    <Application.Styles>
         <StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
         <StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
         <StyleInclude Source="resm:Avalonia.Controls.DataGrid.Themes.Default.xaml?assembly=Avalonia.Controls.DataGrid"/>
    </Application.Styles>

    Мультиселект в TreeView


    В #2347 в TreeView был добавлен мультиселект. Шёл 2019-ый год.


    Улучшенная поддержка ReactiveUI


    В #2294 был добавлен контрол
    RoutedViewHost.


    API системных шрифтов


    Теперь можно получить список всех доступных API в системе. Продолжался 2019-ый год.


    Исправлено множество ошибок


    Перечень (почти) всех изменений можно посмотреть здесь.


    Breaking Changes


    Поскольку мажорный номер версии у нас 0, то согласно SemVer мы можем делать ломающие изменения в минорных релизах. И мы их таки делаем, потому и всё ещё "бета". Перечень с информацией о миграции можно посмотреть тут.


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


    Проще всего установить расширение для Visual Studio и использовать поставляемые с ним шаблоны, либо воспользоваться шаблонами для dotnet new. Примеры работы с тулкитом можно посмотреть
    здесь.


    Про документацию мы пока традиционно можем сказать, у нас примерно как в WPF, что не как в WPF расписано на сайте, а если случилось что-то совсем не понятное, то стучитесь в Gitter-чат/


    А этим вообще кто-то пользуется?


    За всех не скажем, скажем за тех, кто рассказал нам про себя в чатах:


    Кроссплатформенный вариант ILSpy


    WasabiWallet — ZeroLink-совместимый Bitcoin-кошелёк


    PokemonBattleEngine — симулятор боёв покемонов



    egram.tel — клиент Telegram


    SparkSDR — Software-defined Radio для любительских(?) радиостанций.



    RoslynPad — опенсорсный аналог LinqPad.


    Core2D — редактор диаграмм


    AvalonStudio — IDE для embedded-разработки


    ну и для разработки на C# с авалонией:


    Пополнить этот список в ваших силах.

    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 23

      0
      Спасибо, с интересом слежу за проектом, но как-то не доходят руки попробовать.
      Было бы интересно узнать больше реальных кейсов использования.
        0

        Кейсы использования по сути те же, что и у WPF, только кроссплатформенно.


        Ну или вот из последнего, мы в субботу в рамках MskDotNet проводили хакатон по написанию гоночных ботов по заранее неразведанной гексокарте, я к нему прокси-визуализатор для отображения поведения бота и видимых им клеток после запросов к серверу на авалонии делал. Писал сидя на линуксе, участники использовали на Windows и OSX. Соответственно на той же кодовой базе был и редактор карт.

          +2

          Собственно, визуализатор:


          Скрытый текст

          Редактор:


          Скрытый текст

          Т. е. если надо делать приложение под десктоп и вы знаете WPF — можно брать авалонию. Когда допилим поддержку мобилок, можно будет и мобильные приложения писать а ля Flutter.

            +1
            Когда допилим поддержку мобилок ...

            Вот это очень интересно, но наверное достаточно сложно? Какие прогнозы?

          0
          Добрый день! Есть несколько вопросов…
          1. А насколько можно/удобно использовать для разработки приложений продукты jetbrains?
          2. Под win можно ли приложения в трей сворачивать?
            +2
            А насколько можно/удобно использовать для разработки приложений продукты jetbrains?

            Совсем неудобно. Нет превьювера и их XAML-движок не понимает половину наших конструкций. С превьювером мне уже полгода обещают что-то сделать и утверждают, что прогресс есть. По XAML-движку, видимо, придётся нам писать свой плугин


            Под win можно ли приложения в трей сворачивать?

            Пока только руками через P/Invoke. С треем проблема в том, что он, зараза, в 2019-ом году не кроссплатформенный по своим концепциям. В частности, на OSX/Linux мы не можем показать к иконке своё меню, нужно обязательно использовать системное. А это отдельная проблема, которая будет решаться в рамках поддержки глобальных (эскспортируемых) меню.

              0
              Пока только руками через P/Invoke. С треем проблема в том, что он, зараза, в 2019-ом году не кроссплатформенный по своим концепциям.

              А разве нельзя что-нибудь типа
              .With(new Win32PlatformOptions { minimizeToTray = true });
              сделать?
              Просто как раз ищу хоть что-нибудь для кроссплатформенных УИ, и так, чтобы не надо было таскать с собой яву или 100500 мегабайт ноды с хромом…
                +1

                На сегодня могу только предложить через Shell_NotifyIcon создать иконку самостоятельно. Нормальная реализация работы с notification area будет скорее всего ближе к 0.9.

                  0
                  Спасибо! Ждем :)
              0
              знаю, что коммент устарел, но
              1) резко стало удобнее
              2) + еще и в райдере превьювер пилят
              0
              что-то непонятно как запустить на линуксе egram.tel, скачал, распаковал архив, попытался запустить
              Скрытый текст
              > $ ./Tel.Egram                                                                ⬡ 10.14.1 
              
              Unhandled Exception: System.DllNotFoundException: Unable to load shared library 'tdjson' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libtdjson: cannot open shared object file: No such file or directory
                 at TdLib.Bindings.LinuxBindings.td_set_log_file_path(IntPtr path)
                 at TdLib.Client.Log.SetFilePath(String path)
                 at Tel.Egram.Registry.<>c__DisplayClass1_0.<AddTdLib>b__0() in /home/vsts/work/1/s/src/Tel.Egram/Registry.cs:line 48
                 at Splat.DependencyResolverMixins.<>c__DisplayClass8_0`1.<RegisterLazySingleton>b__0()
                 at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
                 at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
                 at System.Lazy`1.CreateValue()
                 at Splat.DependencyResolverMixins.GetService[T](IDependencyResolver This, String contract)
                 at Tel.Egram.Registry.<>c__DisplayClass1_0.<AddTdLib>b__1() in /home/vsts/work/1/s/src/Tel.Egram/Registry.cs:line 55
                 at Splat.DependencyResolverMixins.<>c__DisplayClass8_0`1.<RegisterLazySingleton>b__0()
                 at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
                 at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
                 at System.Lazy`1.CreateValue()
                 at Splat.DependencyResolverMixins.GetService[T](IDependencyResolver This, String contract)
                 at Tel.Egram.Registry.<>c__DisplayClass1_0.<AddTdLib>b__3() in /home/vsts/work/1/s/src/Tel.Egram/Registry.cs:line 68
                 at Splat.DependencyResolverMixins.<>c__DisplayClass8_0`1.<RegisterLazySingleton>b__0()
                 at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
                 at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
                 at System.Lazy`1.CreateValue()
                 at Splat.DependencyResolverMixins.GetService[T](IDependencyResolver This, String contract)
                 at Tel.Egram.Registry.<>c__DisplayClass3_0.<AddServices>b__13() in /home/vsts/work/1/s/src/Tel.Egram/Registry.cs:line 213
                 at Splat.DependencyResolverMixins.<>c__DisplayClass8_0`1.<RegisterLazySingleton>b__0()
                 at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
                 at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
                 at System.Lazy`1.CreateValue()
                 at Splat.DependencyResolverMixins.GetService[T](IDependencyResolver This, String contract)
                 at Tel.Egram.Model.Application.AuthenticationLogic.BindAuthentication(MainWindowModel model) in /home/vsts/work/1/s/src/Tel.Egram.Model/Application/AuthenticationLogic.cs:line 20
                 at Tel.Egram.Model.Application.MainWindowModel.<.ctor>b__28_0(CompositeDisposable disposables) in /home/vsts/work/1/s/src/Tel.Egram.Model/Application/MainWindowModel.cs:line 32
                 at ReactiveUI.ViewForMixins.<>c__DisplayClass3_0.<WhenActivated>b__0() in D:\a\1\s\src\ReactiveUI\Activation\ViewForMixins.cs:line 74
                 at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext()
                 at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
                 at System.Reactive.Disposables.CompositeDisposable..ctor(IEnumerable`1 disposables) in D:\a\1\s\Rx.NET\Source\src\System.Reactive\Disposables\CompositeDisposable.cs:line 67
                 at ReactiveUI.ViewModelActivator.Activate() in D:\a\1\s\src\ReactiveUI\Activation\ViewModelActivator.cs:line 84
                 at Tel.Egram.Program.Run(IDependencyResolver resolver) in /home/vsts/work/1/s/src/Tel.Egram/Program.cs:line 71
                 at Tel.Egram.Program.Main(String[] args) in /home/vsts/work/1/s/src/Tel.Egram/Program.cs:line 18
              [1]    4797 abort      ./Tel.Egram
                  
              

                +1

                Чего-то не хватает для загрузки сишной библиотеки для работы с телеграмом, скорее всего libssl-1.0.0. Натравите ldd на libtdjson.so

                  0
                  ага, нужен libssl.so.1.0.0 а в дебиане есть только 1.0.2
                  +1
                  github.com/egramtel/egram.tel/issues/2
                  Видимо не исправили
                    0

                    Там библиотеке libssl версии 1.0.0 нужна. А с libssl целый зоопарк несовместимых между собой версий. Повторюсь, нужно смотреть выхлоп ldd.

                  +1
                  1)Это трей!!!
                  2)Документация
                    0
                    Что по поводу соответствия гайдлайнам fluent-дизайна?
                      0
                      А можно код приложения демонстрирующего темную тему? Хочу посмотреть как такие табы сделали.
                      0
                      Специфичный кейс:
                      Есть ли возможность встраивать кадры сырого рендера на OpenGL / Vulkan / DX / Metal внутрь окон с контролами? (с пересечением / перекрытием кадра контролами или без)
                        0

                        В версии с nuget.org нормально нельзя, только через WriteableBitmap с копированием в CPU-память и обратно и просадкой FPS.


                        Чтобы сделать нормально, нужны https://github.com/AvaloniaUI/Avalonia/pull/2364 (подстановка своей реализации контекста OpenGL/Vulkan) и https://github.com/AvaloniaUI/Avalonia/pull/2371 (прямой доступ к SkCanvas с рендер-потока), которые перед релизом не стали мержить. За подробностями, как реализовать, можно попробовать обратиться к MarchingCube, у них кейс "отрисовать в написанном на авалонии игровом редакторе собственно выхлоп их игрового движка".

                          0

                          Ну и надо понимать, что всё веселье с вещами типа ANGLE и MoltenVK ляжет на вас.

                        Only users with full accounts can post comments. Log in, please.