Cross-platform New Year demo on .NET Core and Avalonia

    " AAA! It's time to rewrite to .NET Coreǃ, " they said, WPF discussed in the comments. So let's check if it is possible to write a cross-platform GUI application in .NET / C #.



    The Christmas mood inspired the idea of ​​making an animation of falling snow. There were such demos under DOS, burning fire, fractals, snow falling on a Christmas tree, and so on.


    As we will see below, this is not only fun, but also allows you to experience the key functionality of the UI framework. Go!


    Creating a project and UI


    For Avalonia there is a Visual Studio Extension with a project template. Install, create Avalonia .NET Core Application. We see the usual WPF App.xamland MainWindow.xaml. However, the project contains netcoreapp1.1;net461, we change to netcoreapp2.0, we are not in the Stone Age.


    The Avalonia extension for the studio contains XAML Designer, but it didn’t work for me. The resharper goes a little crazy in the markup editor, wants to insert explicit namespaces everywhere, so we can do without it too.


    For the rest, we have in our hands the familiar XAML with the usual controls and properties. You can read about all the differences in the documentation .


    For arbitrary drawing, there is the same name WriteableBitmapfrom WPF. A huge plus is that there is no problem drawing from any stream in it; it looks like this:



    using (ILockedFramebuffer buf = writeableBitmap.Lock())
    {
        uint* ptr = (uint*) buf.Address;
       // Рисуем
        *ptr = uint.MaxValue;
    }

    However Image, which is tied to our writeableBitmap will not be updated by itself, it needs to be said InvalidateVisual().


    Thus, we can draw animations in the background thread without loading the UI thread. In addition to Imageadd a couple of sliders to control the snow falling speed and the amount of snowflakes, here everything is standard {Binding Mode=TwoWay}. Plus, the “start over” button is also a standard snap to ICommand. I note that the vector icons on XAML, copied from Google, are used , it functions as expected.


    Entire Layout: MainWindow.xaml


    Snow algorithm


    "Physics"


    Move the snowflake down one pixel. If the pixel is already occupied by a “lying” snowflake, check the points on the left and right, and move to where it is free. Everything is busy - mark the point as "lying". Thus, the rolling of snowflakes from inclined surfaces is achieved.


    Parallax


    To achieve a volumetric effect, we assign a random speed to each snowflake. The lower the speed, the darker the shade we use for drawing.


    For our “physics” to work correctly, it is necessary to move snowflakes no more than 1 pixel per frame. That is, the fastest snowflakes move each frame per pixel, the rest skip some frames. To do this, you can apply the floatcoordinates and simply redraw each snowflake on each frame. Instead, I use two integer shortfields and redraw the snowflake only if it really moved .


    Rendering


    The main idea is to avoid a complete redraw of the frame. We need to somehow store the “lying” snow, user-drawn dots, uploaded images (yes, you can draw with the mouse and load picci with the right click - the snowball will stick to the Christmas trees and inscriptions).


    A simple and effective solution is to use it yourself WriteableBitmap. Let the “permanent” pixels be completely opaque (A = 255), and for moving snowflakes A = 254.


    Falling snowflakes are always a fixed number, position and speed of each stored in the array. As a result, if the snowflake has moved - we erase the point at the old position and draw on the new one. If it has turned into a “lying” one, set the alpha channel of the point to 255, move the live drop back to the top.


    How to run it?


    Thanks to the possibility of drawing directly “live”, a rather sticky thing turned out, try :)


    For all operating systems, the instructions are the same:


    • Install .NET Core SDK
    • git clone https://github.com/ptupitsyn/let-it-snow.git
    • cd let-it-snow/AvaloniaCoreSnow
    • dotnet run

    Conclusion


    .NET Core is young, Avalonia is still in alpha, but now these tools are solving the task! The code is simple and straightforward, no hacks and extra squats, it works fine on Windows, macOS, Linux.


    Alternatives?


    • Qt (harder to use)
    • Java (no normal unsafe)
    • Electron (JavaScript + HTML - no thanks)

    The UI in this demo is very simple, but it uses several of the most important features:


    • Layout (Grid, StackPanel, alignment) - the basis of layout
    • Binding (binding controls to model properties)
    • ItemsControl, ItemsPanel, DataTemplate - work with data collections
    • WriteableBitmap - direct image manipulation
    • OpenFileDialog, native on every platform

    This is already enough to build a UI of any complexity. So we can say that the last gap in the .NET ecosystem is closed: it is possible to create web (ASP.NET Core), mobile (Xamarin) and desktop (Avalonia) applications, while reusing the code by placing it in the .NET Standard libraries.


    References



    Also popular now: