<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Artyom V. Gorchakov on Medium]]></title>
        <description><![CDATA[Stories by Artyom V. Gorchakov on Medium]]></description>
        <link>https://medium.com/@worldbeater?source=rss-860d7c4bb9db------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*tbCMUZPSEwTxrjv1Hwk1iw.jpeg</url>
            <title>Stories by Artyom V. Gorchakov on Medium</title>
            <link>https://medium.com/@worldbeater?source=rss-860d7c4bb9db------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 28 May 2026 00:20:52 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@worldbeater/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Develop Cross-Platform Desktop GUI Apps on Linux with .NET Core]]></title>
            <link>https://medium.datadriveninvestor.com/develop-cross-platform-net-core-desktop-apps-on-linux-with-xaml-bf3dbba9afa0?source=rss-860d7c4bb9db------2</link>
            <guid isPermaLink="false">https://medium.com/p/bf3dbba9afa0</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[dotnet-core]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[linux]]></category>
            <dc:creator><![CDATA[Artyom V. Gorchakov]]></dc:creator>
            <pubDate>Mon, 17 Aug 2020 10:59:48 GMT</pubDate>
            <atom:updated>2023-04-14T08:14:35.375Z</atom:updated>
            <content:encoded><![CDATA[<h3>Develop Cross-Platform Desktop GUI Apps on Linux with .NET Core</h3><h4>Building reactive graphical user interfaces on Ubuntu with XAML</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1010/1*jf-fQtLV-yF4WaQxBLU9wA.png" /><figcaption>Utility app built on Ubuntu 18 KDE with <a href="https://github.com/avaloniaui/avalonia">AvaloniaUI</a>, <a href="https://www.reactiveui.net/">ReactiveUI</a>, and <a href="https://github.com/reactiveui/reactiveui.validation">ReactiveUI.Validation</a> libraries.</figcaption></figure><p>With the initial release of <a href="http://dot.net/">.NET Core</a>, we can now build cross-platform .NET applications using not only Windows, but also macOS, Ubuntu, and other Linux distros. As a full-stack developer who is pretty excited about the evolution of the .NET ecosystem, I use a laptop with Ubuntu and Windows in dual boot, and with .NET Core SDK installed on both operating systems. However, most of the development time I prefer using Ubuntu <a href="https://kde.org/">KDE</a>. On the one hand, the command-line interface in Linux makes a wide variety of problems way easier to solve, including package management, network configuration, and orchestration of <a href="https://www.docker.com/">Docker</a> containers. On the other hand, using the same environment on your production and development servers also offers some benefits.</p><p>However, no cross-platform desktop GUI exists in .NET Core out of the box. Such awesome desktop frameworks as WPF and UWP currently support Windows only, even after WPF was ported to .NET Core. To overcome this issue, Microsoft has recently announced the new <a href="https://devblogs.microsoft.com/dotnet/introducing-net-multi-platform-app-ui/">Multiplatform App UI</a>, planning to target general availability in November of 2021. However, according to the <a href="https://github.com/dotnet/maui#xamarinforms-vs-net-maui">MAUI page on GitHub</a>, Linux devices won’t receive official support from Microsoft. Surely, one could use a framework based on web technologies in order to develop a desktop app, but this can lead to users <a href="https://twitter.com/iamdevloper/status/926458505355235328">complaining about high RAM and CPU usage</a>. In this situation, <a href="http://avaloniaui.net/">AvaloniaUI</a> comes to the rescue!</p><h3>What is AvaloniaUI? 🔥</h3><p><a href="https://avaloniaui.net/">AvaloniaUI</a> is an open-source, free, and feature-rich .NET Core framework, allowing us to build cross-platform apps of any complexity, on any operating system, including Ubuntu, macOS, and Windows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tQ6cJxr-xy6j1emmCe8fMQ.png" /><figcaption>AvaloniaUI is an open-source project supported by the .NET Foundation.</figcaption></figure><p>The framework uses a XAML dialect, which should feel familiar to folks coming from WPF, UWP, or Xamarin Forms worlds. XAML is a markup language that allows describing app UI declaratively, using a concise XML-like syntax. Similarly to WPF and UWP, Avalonia XAML supports the MVVM pattern and data bindings.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LFZR5JHPydMjBtU1AxmUlQ.png" /><figcaption>An example of a valid AvaloniaUI XAML markup with MVVM-style bindings.</figcaption></figure><p>The main difference is, however, in the XAML compilation engine. The XAML markup in AvaloniaUI is type-checked at compile-time, making typos and other markup bugs much easier to discover and fix. Worth noting, that AvaloniaUI supports debugging XAML right in the debugger of your favorite IDE. AvaloniaUI uses the <a href="https://github.com/kekekeks/XamlX">XamlX</a> compiler internally in order to enable these awesome features.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F9VtwwEL1SJM%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D9VtwwEL1SJM&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F9VtwwEL1SJM%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/c7b54e90ece0696ccb4aec584d0e6f6a/href">https://medium.com/media/c7b54e90ece0696ccb4aec584d0e6f6a/href</a></iframe><p>Additionally, AvaloniaUI allows using regular C# code for building user interfaces, and this may seem similar to the technique used in <a href="https://flutter.dev/">Flutter</a>. <a href="https://docs.avaloniaui.net/docs/data-binding/binding-from-code">Binding from code</a> is supported as well, and a specific syntax exists, which allows attaching the bindings to the specified properties in the initializers of C# objects. Worth noting, that IObservables from <a href="http://reactivex.io/">reactive extensions</a> are first-class citizens in AvaloniaUI.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jT8JpFqdWXrADzQCARF59w.png" /><figcaption>Binding to observables and properties in AvaloniaUI.</figcaption></figure><p>The <a href="https://docs.avaloniaui.net/docs/styling/styles">styling system</a> in AvaloniaUI is heavily inspired by CSS and can be thought of as a mix of XAML templates and CSS selectors. From my personal experience, combining these two powerful techniques for building user interfaces is a really cool idea, which greatly simplifies the process of styling a complex application. With a CSS-like selector, you can easily select the required control, and the setters declared in XAML allow using brushes from resource dictionaries. Such resource dictionaries can be changed dynamically at runtime, making theming AvaloniaUI applications incredibly easy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PKuPeMpvFMbtWbdXifw9ig.png" /><figcaption>Styling complex controls and visual states in AvaloniaUI.</figcaption></figure><p>Another cool feature that distinguishes AvaloniaUI from good old technologies like WPF is intelligent <a href="https://docs.avaloniaui.net/docs/templates/data-templates">data templates</a>. Data templates in AvaloniaUI have a DataType property, and the template for the data can be chosen at runtime based on the type of the bound object. The bound object, on its turn, is usually a view model built with <a href="https://reactiveui.net">ReactiveUI</a>. In Avalonia applications, ReactiveUI is used as the MVVM framework by default.</p><p><a href="https://www.datadriveninvestor.com/2020/05/27/clean-code-is-crucial-in-software-development-heres-why/">Clean Code is Crucial in Software Development - Here&#39;s Why | Data Driven Investor</a></p><h3>What is ReactiveUI? 💫</h3><p><a href="https://www.reactiveui.net/">ReactiveUI</a> should feel familiar to folks coming from WPF, UWP, and Xamarin Forms worlds. It is an advanced, composable, reactive MVVM framework for all .NET platforms, with almost 1.5 million downloads on NuGet. ReactiveUI copes gracefully as your application scales, allowing you to avoid overcomplicating things by using the full power of <a href="http://reactivex.io/intro.html">reactive extensions</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*voz3bxByJg1aot9kySf_Ig.png" /><figcaption>ReactiveUI profile on NuGet. ReactiveUI is a mature .NET Foundation project.</figcaption></figure><p>A typical view model made with ReactiveUI may look like the one below. Such code can be placed into a .NET Standard library, and become easily <a href="https://www.reactiveui.net/docs/handbook/view-models/">portable</a> and <a href="https://www.reactiveui.net/docs/handbook/testing/">testable</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MDwvoSXK5ATT4tciVYV-Gg.png" /><figcaption>A typical view model implemented with the <a href="https://www.reactiveui.net/">ReactiveUI</a> framework. Cross-platform and easily testable.</figcaption></figure><p>ReactiveUI allows observing property changes via the <a href="https://www.reactiveui.net/docs/handbook/when-any/">WhenAnyValue</a> extension method. Computed properties are implemented via the <a href="https://www.reactiveui.net/docs/handbook/observable-as-property-helper/">ObservableAsPropertyHelper</a> class, or with the [ObservableAsProperty] attribute, the <a href="https://www.reactiveui.net/docs/handbook/commands/">ReactiveCommand</a> class is the default implementation for the ICommand interface. Such commands are usually bound to buttons, so the buttons stay disabled until the WhenAnyValue condition is satisfied. The sample XAML markup for the SearchViewModel is shown below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LcZ24C2nNJ6iCFtDZ6X3FQ.png" /><figcaption>A possible markup of a view made with AvaloniaUI XAML for the ReactiveUI view model shown above.</figcaption></figure><p>Additionally, ReactiveUI supports view model <a href="https://www.reactiveui.net/docs/handbook/when-activated/">activation</a> and <a href="https://www.reactiveui.net/docs/handbook/routing/">routing</a>. ReactiveUI <a href="https://www.reactiveui.net/docs/handbook/routing/">routing</a> consists of an IScreen, a bunch of IRoutableViewModels, and a platform-specific RoutedViewHost control. AvaloniaUI provides its own <a href="https://docs.avaloniaui.net/guides/deep-dives/reactiveui/routing">implementation</a> of aRoutedViewHost control in <a href="https://docs.avaloniaui.net/guides/deep-dives/reactiveui">Avalonia.ReactiveUI</a> support package.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pFwPd6zIOhQn6z06.png" /><figcaption><a href="https://www.reactiveui.net/docs/handbook/routing/">ReactiveUI routing</a> in one image.</figcaption></figure><p>The ReactiveUI ecosystem includes such helper projects, as <a href="https://github.com/reactiveui/pharmacist">Pharmacist</a>, <a href="https://github.com/reactiveui/dynamicdata">DynamicData</a>, <a href="https://github.com/reactiveui/sextant">Sextant</a>, and others. These tools can give you superpower in building rich and reactive user interfaces. The <a href="https://github.com/reactiveui/reactiveui.validation">ReactiveUI.Validation</a> package contains validation helpers and the implementation for the INotifyDataErrorInfo interface.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*6JxK8qnLDa-63Nr4oFcLeA.gif" /><figcaption>INotifyDataErrorInfo validation in action with <a href="https://github.com/reactiveui/reactiveui.validation">ReactiveUI.Validation</a>.</figcaption></figure><h3>Developing AvaloniaUI Apps on Linux</h3><p>Using the technology stack described above, we can easily build a .NET Core GUI application on Linux, using <a href="https://www.jetbrains.com/rider/">JetBrains Rider</a> as our IDE. There are helper packages such as <a href="https://github.com/worldbeater/Live.Avalonia">Live.Avalonia</a> that can simplify and speed up the GUI development process by adding the hot reload feature to our Avalonia graphical interfaces.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*8lbCBXx_TDodGhxDgQNlMw.gif" /><figcaption><a href="https://github.com/worldbeater/live.avalonia">Live.Avalonia</a> demo running in <a href="https://www.jetbrains.com/rider/">JetBrains Rider</a> on Ubuntu 18.</figcaption></figure><p><a href="https://code.visualstudio.com/">Visual Studio Code</a> IDE from Microsoft can also be used for development.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*bIorGhjBPuqxP3X0OipFOg.gif" /><figcaption><a href="https://github.com/worldbeater/live.avalonia">Live.Avalonia</a> demo running in <a href="https://code.visualstudio.com/">Visual Studio Code</a> on Ubuntu 18.</figcaption></figure><p>In order to get started with building cross-platform .NET Core GUI apps using AvaloniaUI and ReactiveUI on Linux, install the <a href="https://github.com/AvaloniaUI/avalonia-dotnet-templates">templates</a> from GitHub, and follow the <a href="https://docs.avaloniaui.net/guides/basics">tutorial on AvaloniaUI website</a>. Another option is to follow yet another tutorial, which provides detailed instructions about how to set up <a href="https://docs.avaloniaui.net/guides/deep-dives/reactiveui/routing">ReactiveUI routing in an Avalonia app</a>.</p><p>If you experience any issues, head over to <a href="https://gitter.im/AvaloniaUI/Avalonia">AvaloniaUI Gitter</a>, where you can ask any questions and get help from AvaloniaUI maintainers. If you are willing to dive deeply into the described technology stack, check out the following articles:</p><ul><li><a href="https://dev.to/carlos487/avalonia-ui-in-ubuntu-getting-started-2fak">Avalonia UI on Ubuntu: Getting Started</a></li><li><a href="https://medium.com/swlh/cross-platform-gui-for-dotnet-applications-bbd284709600">A Cross-Platform GUI Theme for Desktop .NET Core Applications</a></li><li><a href="https://medium.com/@worldbeater/reactive-mvvm-for-net-platform-175dc69cfc82">Reactive MVVM Pattern on the .NET Platform</a></li><li><a href="https://www.reactiveui.net/blog/2020/07/article-on-reactive-programing">On Reactive Programming</a></li><li><a href="https://www.reactiveui.net/blog/2020/07/article-on-elevated-values">In Praise of Elevated Values</a></li><li><a href="https://www.idiwork.com/avalonia-a-big-candidate-to-create-crossplatform-apps-with-xaml/">Avalonia, a big candidate to create cross-platform apps with XAML</a></li><li><a href="https://www.hanselman.com/blog/WhatWouldACrossplatformNETUIFrameworkLookLikeExploringAvalonia.aspx">What would a cross-platform .NET UI Framework look like? Exploring Avalonia</a></li><li><a href="https://habr.com/ru/post/462307/">Saving Routing State to the Disk in a Cross-Platform .NET Core GUI App with ReactiveUI and Avalonia</a></li><li><a href="https://github.com/AvaloniaCommunity/awesome-avalonia">A curated list of Awesome Avalonia libraries and resources</a></li><li><a href="https://www.reactiveui.net/docs/handbook/">ReactiveUI Handbook</a></li><li><a href="http://introtorx.com/Content/v1.0.10621.0/01_WhyRx.html">Introduction to Reactive Extensions: Getting Started</a></li></ul><p>Thanks for reading!</p><p><strong>Gain Access to Expert View — </strong><a href="https://datadriveninvestor.com/ddi-intel"><strong>Subscribe to DDI Intel</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf3dbba9afa0" width="1" height="1" alt=""><hr><p><a href="https://medium.datadriveninvestor.com/develop-cross-platform-net-core-desktop-apps-on-linux-with-xaml-bf3dbba9afa0">Develop Cross-Platform Desktop GUI Apps on Linux with .NET Core</a> was originally published in <a href="https://medium.datadriveninvestor.com">DataDrivenInvestor</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Cross-Platform GUI Theme for Desktop .NET Core Applications]]></title>
            <link>https://medium.com/swlh/cross-platform-gui-for-dotnet-applications-bbd284709600?source=rss-860d7c4bb9db------2</link>
            <guid isPermaLink="false">https://medium.com/p/bbd284709600</guid>
            <category><![CDATA[user-interface]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[desktop]]></category>
            <category><![CDATA[xaml]]></category>
            <dc:creator><![CDATA[Artyom V. Gorchakov]]></dc:creator>
            <pubDate>Thu, 07 May 2020 13:34:26 GMT</pubDate>
            <atom:updated>2020-09-05T22:29:48.092Z</atom:updated>
            <content:encoded><![CDATA[<h3>A Cross-Platform GUI Theme for Desktop .NET Core Applications</h3><h4>Build beautiful user interfaces with AvaloniaUI</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i3aQ0Do2x5dYbm25Fz9eug.png" /><figcaption>Graphical user interface components of <a href="https://github.com/worldbeater/Citrus.Avalonia">Citrus.Avalonia</a> — a style kit for cross-platform .NET Core <a href="https://github.com/AvaloniaUI">applications</a>. Available for Windows, Linux, and macOS.</figcaption></figure><p><a href="https://avaloniaui.net/">Avalonia</a> is a novel XAML UI framework, allowing .NET developers to deliver cross-platform .NET Core desktop applications for end-users. Inspired by Microsoft stack technologies, such as Xamarin Forms, Windows Presentation Framework, and Universal Windows Platform, Avalonia provides fully-featured means of building high-performant user interfaces of any complexity and any scale. Compared to Windows Presentation Framework, Universal Windows Platform, or Xamarin Forms, Avalonia provides a faster type-safe XAML compiler known as <a href="https://github.com/kekekeks/XamlIl">XamlIl</a>, which makes the process of developing and debugging complex XAML interfaces far less painful. Moreover, <a href="https://github.com/kekekeks/XamlIl">XamlIl</a> allows debugging XAML — watch <a href="https://www.youtube.com/watch?v=9VtwwEL1SJM">this video on YouTube</a> if you are still in doubt about giving Avalonia a try. Avalonia comes with <a href="https://www.reactiveui.net/">ReactiveUI</a> support out of the box, and this makes it possible to use the full power of <a href="https://www.reactiveui.net/docs/reactive-programming/">reactive programming</a> in an Avalonia .NET Core app.</p><p>Known <a href="http://avaloniaui.net/">Avalonia</a> applications include its use in a cross-platform <a href="https://github.com/VitalElement/AvalonStudio">IDE and shell</a>, in <a href="https://github.com/yatli/fvim">code editors</a>, and in privacy-focused <a href="https://github.com/zkSNACKs/WalletWasabi">Bitcoin wallets</a>. Avalonia is shipped as .NET Standard MIT-licensed <a href="https://www.nuget.org/packages/Avalonia/">NuGet packages</a> and is available for free for anyone willing to build cross-platform desktop experiences in C# or F#, even for commercial use.</p><p>However, the <a href="https://github.com/AvaloniaCommunity/awesome-avalonia">ecosystem</a> around the framework is still developing — there aren’t many GUI themes developed for the framework yet. Hence, designing a brand new modern style set seemed reasonable to me. User interface themes in Avalonia were designed as standalone components that can be easily replaced with any other sets of styles, and this made the development process of different color schemes even more simple and convenient.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RGqZge5ck5K6oK11-60n5w.png" /><figcaption>XAML markup of Avalonia CSS-like <a href="http://avaloniaui.net/docs/styles/styles">styles</a> attached to a Window.</figcaption></figure><p>The <a href="http://avaloniaui.net/docs/styles/styles">styling system</a> in Avalonia can be thought of as a mix of <a href="https://www.w3schools.com/css/css_intro.asp">CSS styling</a> and <a href="https://docs.microsoft.com/en-us/dotnet/desktop-wpf/fundamentals/styles-templates-overview">WPF styling</a>, a style consists of a selector and a collection of setters. Styles can be defined on any control, importing styles from files or packages is supported as well.</p><p>Avalonia styling system also supports pseudo-classes, which allows us to control the look of controls in different visual states. With the help of this feature, we can easily change the background of a button when a user presses it, or when a user moves the mouse over the control. Using the /template/ syntax, we can style the primitives based on which a more complex control is built. Dynamic and static resources are also supported, which may seem familiar for those coming from WPF, UWP, or Xamarin Forms.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*k23arZrUupPl3051rPH3Qg.png" /><figcaption>XAML markup of TextBox template adjustment via a CSS-like pseudo-class and a dynamic brush.</figcaption></figure><p>Based on the mentioned implementation details, a novel graphical user interface theme was introduced and packed as a <a href="https://www.nuget.org/packages/Citrus.Avalonia/">NuGet package</a>. The theme received the name Citrus because of the orange accent color used in most of the color schemes available in the Citrus.Avalonia <a href="https://www.nuget.org/packages/Citrus.Avalonia/">NuGet package</a>. Following the licensing policy of the Avalonia framework, the Citrus theme is MIT-licensed and free for everyone, even for commercial use. The source code of the project is available <a href="https://github.com/worldbeater/citrus.avalonia">on GitHub</a>.</p><h3>Getting Started</h3><p>If you are completely new to Avalonia, see <a href="https://avaloniaui.net/docs/quickstart/create-new-project">Avalonia Getting Started</a> tutorial on their documentation website. After you have created the Avalonia .NET Core project, the Citrus.Avalonia package can be installed by either using the NuGet package manager GUI of any IDE, including <a href="https://www.jetbrains.com/rider/">JetBrains Rider</a> and <a href="https://visualstudio.microsoft.com/">Microsoft Visual Studio</a>. Another way is to execute the following <a href="https://dotnet.microsoft.com/download">.NET Core SDK</a> command from your project root:</p><pre>dotnet add package Citrus.Avalonia</pre><p>Then, place the following XAML code into the App.xaml file:</p><pre>&lt;Application xmlns=&quot;https://github.com/avaloniaui&quot;<br>             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;<br>             x:Class=&quot;YourNamespace.App&quot;&gt;<br>  &lt;Application.Styles&gt;<br>    &lt;StyleInclude Source=&quot;avares://Citrus.Avalonia/Citrus.xaml&quot;/&gt;<br>  &lt;/Application.Styles&gt;<br>&lt;/Application&gt;</pre><p>The StyleInclude line is responsible for importing a set of styles into the application. The imported styles will be applied to all default XAML controls, descendant to the element which contains the StyleInclude line. As a result of the code snippet above, all default controls in your application will start using Citrus styles. If you are willing to apply the styles to a small part of your application, move the StyleInclude line to the Styles section of control other than Application . Notably, the Citrus NuGet package includes a dark color scheme as well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oaXD7NkT1VGXmVmZIMtp_g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BIAOXMJ5ho2RgW8LZNpMTw.png" /><figcaption>Light (Citrus) and dark (Sea) themes included in <a href="https://www.nuget.org/packages/Citrus.Avalonia/">Citrus.Avalonia NuGet package</a>.</figcaption></figure><p>To browse the control gallery, clone the Citrus.Avalonia.Sandbox <a href="https://github.com/worldbeater/Citrus.Avalonia/blob/master/src/Citrus.Avalonia.Sandbox/MainWindow.xaml">sample project</a>. There are five color schemes total available inside the Citrus.Avalonia NuGet package, named Citrus, Sea, Rust, Candy, and Magma. In order to use color schemes other than the default one, you need to adjust the StyleInclude XAML tag by changing the Source attribute to point to another color scheme. To avoid collisions, remember to remove other StyleInclude lines present in the App.xaml file before.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rmCofeRJIe8CJAmBnsFhxA.png" /><figcaption>To use different Citrus.Avalonia color schemes, comment out all &lt;StyleInclude /&gt; lines and uncomment one necessary line. Head over to <a href="https://github.com/worldbeater/Citrus.Avalonia">README.md</a> to copy-paste the contents shown in the picture.</figcaption></figure><h3>Changing Color Schemes Dynamically</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*iy6I-lufqRVPeslP.gif" /><figcaption>Dynamically changing color schemes in Citrus.Avalonia <a href="https://github.com/worldbeater/Citrus.Avalonia/tree/master/src/Citrus.Avalonia.Sandbox">sandbox project</a>.</figcaption></figure><p>In order to provide end-users the ability to change graphical user interface themes dynamically, move the StyleInclude line to a control other than Application . The StyleManager class shown below takes in a Window via the constructor, and provides the ability to change UI themes at runtime via the UseTheme method invocation.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6c7b8f2ed89abd5cbd28387766c8abfc/href">https://medium.com/media/6c7b8f2ed89abd5cbd28387766c8abfc/href</a></iframe><p>See <a href="http://avaloniaui.net/docs/styles/styles">Avalonia Documentation</a> for further details about building custom themes and adjusting styles. The <a href="https://github.com/worldbeater/Citrus.Avalonia">source code</a> of the Citrus theme described in this post may help as well, in case if you are going to build your own GUI theme. The <a href="https://github.com/worldbeater/Citrus.Avalonia/tree/master/src/Citrus.Avalonia.Sandbox">sandbox project</a> contains the control gallery shown in the pictures contained in this post. If you encounter any issues regarding the Avalonia GUI framework or the <a href="https://github.com/worldbeater/Citrus.Avalonia">Citrus theme</a>, head over to <a href="https://gitter.im/AvaloniaUI/Avalonia">Avalonia Gitter</a>. See the article <a href="https://medium.com/@worldbeater/reactive-ui-fody-cross-platform-forms-7b501d79f46b">Building Cross-Platform Reactive .NET Apps</a> for more insight into the architecture used in XAML-based cross-platform C# applications.</p><p>Further work could cover more UI design guidelines. Folks from the Avalonia community have started working on the <a href="https://github.com/CreateLab/material.avalonia">Material Design</a> theme. Additionally, worth implementing the new <a href="https://www.microsoft.com/design/fluent/">Microsoft Fluent Design System</a> and <a href="https://developer.apple.com/design/">Apple Human Interface Guidelines</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bbd284709600" width="1" height="1" alt=""><hr><p><a href="https://medium.com/swlh/cross-platform-gui-for-dotnet-applications-bbd284709600">A Cross-Platform GUI Theme for Desktop .NET Core Applications</a> was originally published in <a href="https://medium.com/swlh">The Startup</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Story Of Reliable Code]]></title>
            <link>https://worldbeater.medium.com/a-story-of-reliable-code-53293144f822?source=rss-860d7c4bb9db------2</link>
            <guid isPermaLink="false">https://medium.com/p/53293144f822</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[object-oriented]]></category>
            <category><![CDATA[fsharp]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[functional-programming]]></category>
            <dc:creator><![CDATA[Artyom V. Gorchakov]]></dc:creator>
            <pubDate>Thu, 01 Nov 2018 12:03:25 GMT</pubDate>
            <atom:updated>2023-04-20T22:20:43.590Z</atom:updated>
            <content:encoded><![CDATA[<h4>How compile-time checks assist .NET devs in delivering software</h4><p>Imagine you are a C# programmer designing API of a tiny search engine. The engine is really simple — it searches for goods in a database using a query string provided by a user. You sit down, decide not to focus on implementation details yet, and write a simple C# interface:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uEyEHH8LUAOE_MzSFVgzvA.png" /></figure><p>Fine. You still don’t want to focus on implementation details, you’d like to ask someone to implement that interface for you. But before doing that, you ask yourself — what will happen, if your mate writes buggy code and such code passes code review? You decide to analyze potential issues and try to eliminate them. So, what’s wrong with the contract defined above?</p><ol><li>The Search method accepts a string. C# doesn’t prevent you from passing null instead of a string to that method, but will the search engine implementation handle the null value correctly? Will it fail fast or return some search results? No answer.</li><li>The Search method returns a Task&lt;T&gt; , which can also be null. Yeah, it is a really bad practice to return null from methods returning tasks, but bad things happen.</li><li>The Search method can return a Task containing a null value. Is this meant to be correct behavior or not, what that null value means — again, no answer.</li><li>The search method executes correctly, consumes a query string, and returns a sequence of search results. Assuming SearchResult is a reference type, is there any guarantee, that our program will never fail with NullReferenceException when we try to access a SearchResult instance property in our code? No, we have to trust the implementation details.</li><li>Exceptions. Who knows, what exceptions a custom search engine might throw. The exceptions apparently are not documented anywhere yet.</li></ol><p>If you use JavaScript without type annotations, the issues amount is actually a lot bigger than those 5 mentioned applicable to C#. Assuming all the above, the safe way of calling the ISearchEngine.Search method is something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WutEUhwKaOPvXkiZcUxKSw.png" /><figcaption>Highlighted by <a href="https://carbon.now.sh/">carbon.now.sh</a></figcaption></figure><p>No one writes such code! Most time we don’t handle all these cases separately and simply let the program fail at run time if anything goes wrong. This means if we use a bad interface implementation, our software will likely crash.</p><h3>Make Contracts More Reliable</h3><p>Willing to make the contract more reliable, you, as a C# developer, download <a href="https://blog.jetbrains.com/dotnet/2018/05/03/what-are-jetbrains-annotations/">JetBrains.Annotations</a> NuGet package, and annotate the code snippet above.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KooEVV6FkuYhNyIgMWWjnQ.png" /><figcaption>Highlighted by <a href="https://carbon.now.sh/">carbon.now.sh</a></figcaption></figure><p>This is definitely better. You mark your input and output parameters with the NotNull and ItemNotNull attributes — so the project won’t compile if someone tries to use null s anywhere. Additionally, you document all possible exceptions that a search engine implementation might throw — so one can omit the global try catch block when working with that interface. Now, one can call the ISearchEngine.Search method safely!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8ALhMay0vPnDqHD_14_w0w.png" /><figcaption>Highlighted by <a href="https://carbon.now.sh/">carbon.now.sh</a></figcaption></figure><p>This is the best way of resolving such issues with C#, but it isn’t a silver bullet. The person who implements the ISearchEngine interface can easily ignore recommendations defined in the signature, or turn <a href="https://www.jetbrains.com/resharper/">ReSharper</a> off. So, what do we have to do to absolutely trust our code base?</p><h3>Write Unit Tests For Interface Implementations</h3><p>This is quite obvious, and prevents our software from unexpected errors in most cases, but sometimes requires doing a ton of work each time the API changes. That’s why we move forward and try to learn new tools.</p><h3>Use F#, Functional Programming and Types</h3><p>F# is a strongly typed, multi-paradigm programming language that encompasses functional, imperative, and object-oriented programming methods. F# runs everywhere C# does.</p><p>Considering our search engine implementation, the first benefit we get when using F# is null safety. This means a reference type can never implicitly be null in F#. For example, a string variable can never be null, if we need to store a null value inside it, we use Nullable&lt;string&gt; type.</p><p>Yeah, no more null reference exceptions. Hopefully, <a href="https://blogs.msdn.microsoft.com/dotnet/2017/11/15/nullable-reference-types-in-csharp/">null safety is going to be introduced</a> in C#8. But now, if we rewrite our C# interface declared above in F#, we’ll eliminate four of five issues from our list! The only issue left is related to exceptions that are not documented.</p><p>Functional programmers don’t like exceptions. Although one can write a <em>pure</em> function that uses raise statements under the hood, exceptions <a href="https://medium.com/@olxc/referential-transparency-93352c2dd713">violate referential transparency</a>. Instead of exceptions, it’s better to use explicitly typed output and <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/discriminated-unions">discriminated unions</a>.</p><p>Assuming that, let’s refactor the C# interface declared above into F# types.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9w-6uGZKpaOkYHp1ZBeX0w.png" /><figcaption>Highlighted by <a href="https://carbon.now.sh/">carbon.now.sh</a></figcaption></figure><p>Here we describe all possible values that a function may produce, including errors, using a SearchResponse discriminated union. Instead of using implicit exceptions and XML documentation, we use types, and our code becomes self-documenting. Instead of using an interface here, we use a functional type. The search engine becomes a function that takes a query string and returns a response asynchronously. “Implementing” and using such function is simple.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*POLg8ricRlbveXMfgHMOUw.png" /><figcaption>Highlighted by <a href="https://carbon.now.sh/">carbon.now.sh</a></figcaption></figure><p>We can finally trust the search engine implementation. Our app will never fail with null reference exceptions, and compiler forces us to handle all errors that a function may return, using pattern matching over a <a href="http://blog.ploeh.dk/2018/06/25/visitor-as-a-sum-type/">discriminated union</a>. If we don’t handle all cases, we’ll receive a warning each time we are attempting to build the project. Far better!</p><p>Yeah, sounds tricky at first glance. If you find yourself interested and would like to learn more, visit <a href="https://fsharpforfunandprofit.com/why-use-fsharp/">F# For Fun and Profit website</a>. Additionally, it’s worth reading “<em>Domain Modelling Made Functional: Tackle Software Complexity with Domain-Driven Design and F#</em>” book by <a href="https://github.com/swlaschin">Scott Wlaschin</a> for more real-world code examples and best practices. Code snippets in this article are highlighted using <a href="https://carbon.now.sh/">carbon.now.sh</a> online service.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=53293144f822" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Funogram: Writing Telegram Bots In F#]]></title>
            <link>https://worldbeater.medium.com/funogram-writing-telegram-bots-in-f-f27a873fa548?source=rss-860d7c4bb9db------2</link>
            <guid isPermaLink="false">https://medium.com/p/f27a873fa548</guid>
            <category><![CDATA[functional-programming]]></category>
            <category><![CDATA[dotnet-core]]></category>
            <category><![CDATA[bots]]></category>
            <category><![CDATA[telegram]]></category>
            <category><![CDATA[fsharp]]></category>
            <dc:creator><![CDATA[Artyom V. Gorchakov]]></dc:creator>
            <pubDate>Sun, 03 Jun 2018 21:28:41 GMT</pubDate>
            <atom:updated>2021-05-03T22:57:51.460Z</atom:updated>
            <content:encoded><![CDATA[<h4>Getting started with a new .NET Telegram Bot API library</h4><p><a href="https://telegram.org/">Telegram</a> is a secure instant messaging service providing a platform that allows creating bots — the <a href="https://telegram.org/blog/bot-revolution">Telegram Bot API</a>. A Bot is a Telegram account <a href="https://core.telegram.org/bots">operated by software</a>. There are Bot API implementations for almost every popular programming language, including <a href="https://github.com/eternnoir/pyTelegramBotAPI">Python</a>, <a href="https://github.com/yagop/node-telegram-bot-api">JavaScript</a>, and <a href="https://github.com/TelegramBots/Telegram.Bot">C#</a>. <a href="https://github.com/Dolfik1/Funogram">Funogram</a> is a strictly typed Telegram Bot API wrapper built completely in <a href="https://fsharp.org/">F#</a>, a cross-platform functional-first programming language. If you are new to F#, check <a href="https://fsharpforfunandprofit.com/why-use-fsharp/">this guide</a> to get started. In this article, we are going to build our first Telegram Bot using F#, Funogram, and .NET Core.</p><h3>Getting Started</h3><p>First, we need to download <a href="https://www.microsoft.com/net">.NET Core SDK</a> and an IDE we’d like to use — <a href="https://www.visualstudio.com">Visual Studio</a>, <a href="https://www.jetbrains.com/rider/">Rider</a>, or <a href="https://code.visualstudio.com/">Visual Studio Code</a> with <a href="http://ionide.io/">Ionide plugin</a>. To initialize a simple F# console application, we use <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet">.NET CLI</a>:</p><pre>dotnet new console --lang F#</pre><p>Then we need to install <a href="https://www.nuget.org/packages/Funogram/">Funogram</a> and download the missing packages:</p><pre>dotnet add package Funogram &amp;&amp; dotnet restore</pre><p>From that point, we can start writing F# code!</p><h3>Creating a Listener</h3><p>The easiest way to communicate with Telegram servers is through long-polling. Long-polling is an emulation of pushing data, implemented by repeated polling with a delayed response. The good news is, that Funogram takes care of this for us and the only thing we have to do is to invoke the startBot function, so every update received from Telegram will trigger our handler.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b1c3694a285f54ab9ce19b36443e7238/href">https://medium.com/media/b1c3694a285f54ab9ce19b36443e7238/href</a></iframe><p>Note that we don’t have to specify the type of function parameter context explicitly (it is Funogram.Bot.UpdateContext indeed), the compiler analyzes our code and <a href="https://fsharpforfunandprofit.com/posts/type-inference/">infers types for us</a>. bot-token is a Telegram Bot token received from <a href="https://telegram.me/BotFather">Bot Father</a>. Let’s run our code to see if everything goes well:</p><pre>dotnet run</pre><h3>Handling Commands</h3><p>Now it’s time to extend the functionality of our bot. Let’s teach him to greet users. The Funogram library uses <a href="https://fsharpforfunandprofit.com/posts/the-option-type/">Option Monads</a> for handling optional Telegram API response values instead of nullability. To simplify our codebase and to avoid huge <a href="https://fsharpforfunandprofit.com/posts/match-expression/">pattern matching</a> nestings we can install the <a href="https://github.com/jack-pappas/ExtCore">ExtCore</a> library and use a <a href="https://github.com/jack-pappas/ExtCore/blob/42d629bc434248f77c2a8fc663b92167079d071f/ExtCore/Control.fs#L706">MaybeBuilder</a> from theExtCore.Control module.</p><pre>dotnet add package ExtCore &amp;&amp; dotnet restore</pre><p>If you are new to monads and computation expressions, <a href="https://medium.com/real-world-fsharp/understanding-monads-db30eeadf2bf">this article</a> may help you get started. Funogram provides Funogram.Api.processCommands function allowing us to link commands to handlers. sendMessage constructs a request to Telegram Bot API, and api builds an asynchronous operation we need to start using Async.Start function.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dc074d159879570dea625d6fb1343ea9/href">https://medium.com/media/dc074d159879570dea625d6fb1343ea9/href</a></iframe><p>Now our Telegram bot can greet users!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1005/1*UrdXjRfBZGwUkeXfzbBuBQ.png" /><figcaption>Telegram bot greets ‘/hello’ command issuer</figcaption></figure><h3>Further Learning</h3><p>Funogram sources are available on <a href="https://github.com/Dolfik1/Funogram">GitHub</a>. The complete Telegram Bot API reference can be found <a href="https://core.telegram.org/bots">here</a>, F# types and functions — <a href="https://github.com/Dolfik1/Funogram/blob/master/src/Funogram.Telegram/Types.fs">here</a> and <a href="https://github.com/Dolfik1/Funogram/blob/master/src/Funogram.Telegram/Api.fs">here</a>. If you get the Unable to read data from the transport connection exception, then it seems that Telegram is blocked in your country and you may need to <a href="https://github.com/Dolfik1/Funogram/blob/master/src/Funogram.TestBot/Program.fs#L145">set up a proxy</a>. If you have any additional questions, feel free to ask the community on <a href="https://fsharp.org/guides/slack/">Slack</a> or <a href="http://t.me/fsharp_chat">Telegram</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f27a873fa548" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building Cross-Platform Reactive .NET Apps]]></title>
            <link>https://worldbeater.medium.com/reactive-ui-fody-cross-platform-forms-7b501d79f46b?source=rss-860d7c4bb9db------2</link>
            <guid isPermaLink="false">https://medium.com/p/7b501d79f46b</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[uwp]]></category>
            <category><![CDATA[wpf]]></category>
            <category><![CDATA[xamarin-forms]]></category>
            <category><![CDATA[mvvm]]></category>
            <dc:creator><![CDATA[Artyom V. Gorchakov]]></dc:creator>
            <pubDate>Sat, 24 Feb 2018 15:32:42 GMT</pubDate>
            <atom:updated>2021-04-25T10:56:12.045Z</atom:updated>
            <content:encoded><![CDATA[<h3>Build Cross-Platform Reactive .NET Apps</h3><h4>Validating forms with ReactiveUI and Fody</h4><p>In the <a href="https://medium.com/@worldbeater/reactive-mvvm-for-net-platform-175dc69cfc82">previous article</a>, we took a look at several ways of implementing the MVVM pattern on the .NET platform. We found out, that the simplest approach is to use assembly weaving with reactive <a href="https://reactiveui.net/">bindings</a> and <a href="http://reactivex.io/">extensions</a>. Now we are going to build a sample application using these techniques. Let’s start with the most common task — form validation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/952/1*7mnGV40TNGSNIWUVTQR0yw.png" /><figcaption>Code sharing in a nutshell with the MVVM architecture.</figcaption></figure><h3>Getting Started</h3><p>The MVVM (<em>Model-View-ViewModel</em>) architectural pattern enforces the separation between three software layers, so we can think of extracting the layers into different assemblies. In order to achieve this, worth taking a look at <a href="https://docs.microsoft.com/en-us/dotnet/standard/net-standard">.NET Standard</a> — a formal specification of .NET APIs that are available across all .NET implementations.</p><p>Using the MVVM architectural approach and .NET Standard code sharing strategy, we can share our ViewModel and Model layers across multiple XAML UI frameworks. If we’ve built an app for the <a href="https://docs.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide">Universal Windows Platform</a>, it would be rather easy to port it to other UI frameworks, such as <a href="https://www.xamarin.com/">Xamarin Forms</a>, <a href="https://github.com/AvaloniaUI/Avalonia">Avalonia</a>, or <a href="https://msdn.microsoft.com/en-us/library/aa970268(v=vs.100).aspx">Windows Presentation Foundation</a> — UI will be <em>the only thing </em>we’ll need to build from scratch.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/826/1*2hu68Yy5BfIFrxYTDhJDaw.png" /><figcaption>Cross-platform .NET application architecture diagram created using <a href="https://www.jetbrains.com/help/resharper/Reference__Architecture_View.html">ReSharper Architecture View</a> tool</figcaption></figure><p><a href="https://www.nuget.org/packages/reactiveui/8.0.0-alpha0117">ReactiveUI</a> and <a href="https://www.nuget.org/packages/PropertyChanged.Fody/">ReactiveUI.Fody</a> libraries are fully compatible with .NET Standard, so we’ll use them in our sample application.</p><h3>Form Validation Logic</h3><p>Now we are ready to create our first reactive view model and populate it with some logic. Imagine we are developing a complex system and would like to gather feedback from users.</p><p>When a user sends us a message, we need to know whether the message is a bug report or a feature suggestion, we also need to group messages by categories. Users shouldn’t be able to submit feedback until they provide all the necessary information. A view model satisfying these conditions might look like the one below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/898134a60eeaef85d1afdc3b1ef381da/href">https://medium.com/media/898134a60eeaef85d1afdc3b1ef381da/href</a></iframe><p>We mark the properties of our view model class with Reactive attributes— so all the marked properties will notify our UI when their values change. Using the <a href="https://reactiveui.net/docs/handbook/when-any/">WhenAnyValue</a> extension method, we can subscribe to such notifications. A call to WhenAnyValue returns anIObservable&lt;T&gt;, where T represents the type of the observed property value. Then, we apply the Where operator from reactive extensions that allows us to filter irrelevant events. Inside a lambda passed to the Subscribe method, we perform another view model property mutation.</p><p>WhenAnyValue allows us to observe as many properties as we would like to, so we validate the whole form each time any of the form fields change. The Log extension method is a magic utility that logs all values emitted by an observable to the debug output. There are <a href="https://github.com/reactiveui/splat">logging adapters</a> for NLog, Serilog, and Log4Net. The <a href="http://reactivex.io/documentation/operators/publish.html">Publish</a> and <a href="http://reactivex.io/documentation/operators/refcount.html">RefCount</a> operators are used to ensure the observable event stream will be subscribed only once. We pass the IObservable&lt;bool&gt; to the <a href="https://reactiveui.net/docs/handbook/commands/">ReactiveCommand</a> that is responsible for form submitting, so the command will stay disabled until a user fills the form up.</p><p>We mark the view model class with <a href="https://reactiveui.net/docs/handbook/logging/">IEnableLogger</a> and <a href="https://reactiveui.net/docs/handbook/when-activated/">IActivatableViewModel</a> interfaces. The former is used to enable logging extensions, and the latter is used to enable the <a href="https://reactiveui.net/docs/handbook/when-activated/">WhenActivated</a> feature. The DisposeWith extension method attaches the disposable produced by the Subscribe method call to the CompositeDisposable that will be disposed of once the view model deactivates.</p><h3>Unit Testing</h3><p>Testing is an important part of the software development process. We can use <a href="https://xunit.github.io/">XUnit</a> to run unit tests either on .NET Core or on .NET Framework. The <a href="http://nsubstitute.github.io/">NSubstitute</a> library allows us to easily generate stubs and mocks, and <a href="http://fluentassertions.com/">FluentAssertions</a> can improve the readability of our tests’ stack traces. Let’s write a test to ensure our presentation logic performs as expected!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7606cae23e29bdf394e1c7b53f0cad75/href">https://medium.com/media/7606cae23e29bdf394e1c7b53f0cad75/href</a></iframe><h3>UI For Universal Windows Platform</h3><p>Creating a presentation part of the application is simple: we need to declare controls in <a href="https://en.wikipedia.org/wiki/Extensible_Application_Markup_Language">XAML</a>, and bind their values to view model’s properties and commands. Here is the code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3ea4ee01bba9bbf53013850bc42bcddb/href">https://medium.com/media/3ea4ee01bba9bbf53013850bc42bcddb/href</a></iframe><p>We need to implement the IViewFor&lt;TViewModel&gt; interface in our platform-specific view class. This makes <a href="https://reactiveui.net/docs/handbook/when-activated">activation and deactivation</a> feature available for both our view and the associated view model. The view model should implement the IActivatableViewModel interface. A call to WhenActivated added to the view constructor will activate the corresponding view model.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c04fe19c87e5325c1eefb2719f549110/href">https://medium.com/media/c04fe19c87e5325c1eefb2719f549110/href</a></iframe><p>Finally, we get a good-looking feedback form component!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/849/1*HltVa3o_q4MhBc8tBLhjug.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/821/1*EsqN0dFMCUknKc-4wuIanA.png" /><figcaption>Feedback Form component built using <a href="https://docs.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide">Universal Windows Platform</a>, <a href="https://reactiveui.net/">ReactiveUI</a>, and ReactiveUI.Fody</figcaption></figure><h3>UI For Xamarin Forms</h3><p>In order to port the app to Android devices, we create a new <a href="https://developer.xamarin.com/guides/xamarin-forms/getting-started/">Xamarin.Forms</a> project from <a href="https://www.visualstudio.com">Visual Studio</a> templates and add a reference to our .NET Standard class library containing view models. XAML markup will look like the one created for the Universal Windows Platform, but we’ll use cross-platform mobile-friendly controls provided by <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/get-started/">Xamarin.Forms</a>. We also install <a href="https://reactiveui.net/docs/getting-started/installation/nuget-packages/">ReactiveUI.AndroidSupport</a> package into the Xamarin.Android project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d1oeBQF9ilZ5h_IIhYktPQ.png" /><figcaption>Feedback Form component built using <a href="https://www.xamarin.com/">Xamarin.Forms</a>, <a href="https://reactiveui.net/">ReactiveUI</a>, and ReactiveUI.Fody</figcaption></figure><h3>UI For Avalonia &amp; Windows Presentation Foundation</h3><p>It’s really easy now to port our application to <a href="https://github.com/AvaloniaUI/">Avalonia</a> and <a href="https://msdn.microsoft.com/en-us/library/aa970268(v=vs.100).aspx">Windows Presentation Foundation</a> frameworks. For each framework, we create a platform-specific project and reference our .NET Standard class library. Also, we install ReactiveUI platform-specific packages according to the <a href="https://reactiveui.net/docs/getting-started/installation/nuget-packages/">ReactiveUI installation guide</a>. From that point, we can start building the UI.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/891/1*JPlUC1YoAuE2eFng29LpaQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/891/1*A7-iy9RwQLBTJ9kZYNG_sA.png" /><figcaption>Feedback form component built using AvaloniaUI, ReactiveUI, and ReactiveUI.Fody. The modern <a href="https://github.com/worldbeater/citrus.avalonia">Citrus.Avalonia</a> theme is used here.</figcaption></figure><h3>UI For Windows Forms</h3><p>Another useful feature ReactiveUI provides is <a href="https://reactiveui.net/docs/handbook/data-binding/">type-safe binding</a> that can be used on any platform, even if it isn’t XAML-based. For example, with <a href="https://reactiveui.net/docs/getting-started/installation/windows-forms">ReactiveUI.WinForms</a> package we can use the MVVM pattern with Windows Forms. In order to have the bindings working, we create a new form, implement the IViewFor interface, and place the binding extension methods into the <a href="https://reactiveui.net/docs/handbook/when-activated/">WhenActivated</a> block.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5d35c2265e92dc215d6e6bda7da20ec0/href">https://medium.com/media/5d35c2265e92dc215d6e6bda7da20ec0/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/394/1*GGwXG5-u_Gc-yMCj8Q1tqQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/394/1*3UNayA_oY9euIJk83n7WNw.png" /><figcaption>Feedback form component built using Windows Forms, ReactiveUI, and ReactiveUI.Fody</figcaption></figure><p>As we see, .NET stack allows us to build truly cross-platform software — using <a href="https://docs.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide">UWP</a>, <a href="https://www.xamarin.com/forms">Xamarin.Forms</a>, <a href="https://docs.microsoft.com/en-us/visualstudio/designers/create-modern-desktop-applications-with-windows-presentation-foundation">WPF</a>, and <a href="https://github.com/AvaloniaUI/Avalonia">Avalonia UI</a> XAML frameworks we can bring our applications to devices running Android, iOS, Windows, Linux, and macOS operating systems. The MVVM pattern and such libraries, as <a href="http://reactiveui.net/">ReactiveUI</a> and <a href="https://github.com/Fody/Fody">Fody</a>, can simplify the process of creating portable software, allowing developers to write clear and maintainable code.</p><p>The source code of the application described in this article can be found on GitHub: <a href="https://github.com/worldbeater/ReactiveMvvm">https://github.com/worldbeater/ReactiveMvvm</a> ✨ Additionally, worth taking a look at a <a href="https://github.com/worldbeater/Camelotia">cross-platform application</a> that demonstrates the usage of all the features described above. That application can be considered as a more comprehensive example, which is compatible with Windows, Linux, macOS, and Android.</p><p>Worth noting that additional validation helpers are available in the new <a href="https://github.com/reactiveui/reactiveui.validation">ReactiveUI.Validation</a> NuGet package. ReactiveUI.Validation includes INotifyDataErrorInfo implementation, helpers that allow to attach and detach validation rules dynamically, and the BindValidation extension method. The ReactiveUI.Validation library is cross-platform and could be used in both mobile and desktop apps that require complex validations.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7b501d79f46b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reactive MVVM Pattern On The .NET Platform]]></title>
            <link>https://worldbeater.medium.com/reactive-mvvm-for-net-platform-175dc69cfc82?source=rss-860d7c4bb9db------2</link>
            <guid isPermaLink="false">https://medium.com/p/175dc69cfc82</guid>
            <category><![CDATA[wpf]]></category>
            <category><![CDATA[reactive-programming]]></category>
            <category><![CDATA[xamarin-forms]]></category>
            <category><![CDATA[uwp]]></category>
            <category><![CDATA[mvvm]]></category>
            <dc:creator><![CDATA[Artyom V. Gorchakov]]></dc:creator>
            <pubDate>Sun, 28 Jan 2018 15:09:30 GMT</pubDate>
            <atom:updated>2021-05-03T23:03:12.556Z</atom:updated>
            <content:encoded><![CDATA[<h3>Reactive MVVM on the .NET Platform</h3><h4>Implementing the MVVM pattern with ReactiveUI and Fody</h4><p>A portable and maintainable codebase is important, especially in large-scale and cross-platform .NET implementations. On XAML-based platforms, such as <a href="https://docs.microsoft.com/en-us/visualstudio/designers/create-modern-desktop-applications-with-windows-presentation-foundation">Windows Presentation Foundation</a> (WPF), <a href="https://docs.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide">Universal Windows Platform</a> (UWP), <a href="https://www.xamarin.com/forms">Xamarin Forms</a>, and <a href="https://github.com/AvaloniaUI/Avalonia">AvaloniaUI</a> you can achieve maintainability goals by implementing the MVVM pattern.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/952/1*_L0SsHwq5uboIQO9knrefA.png" /><figcaption>The MVVM pattern in a nutshell.</figcaption></figure><p>MVVM stands for <a href="https://msdn.microsoft.com/ru-ru/library/hh848246.aspx">Model-View-ViewModel</a>, where Model represents services, data transfer objects, and database entities related to the application domain, View is the UI and ViewModel’s responsibility is to tie these two layers together in a convenient way. ViewModel encapsulates interaction with Model, exposing properties and commands for XAML UI to bind to.</p><h3><strong>Traditional MVVM Implementation</strong></h3><p>To make bindings work a typical ViewModel should implement the <a href="https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx">INotifyPropertyChanged</a> interface and call the PropertyChanged event when any of ViewModel’s properties change. A straightforward implementation may look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1098629e22fca1dee9efcfa7164f9b6c/href">https://medium.com/media/1098629e22fca1dee9efcfa7164f9b6c/href</a></iframe><p>With the following XAML describing our UI:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3ae6a80d526c71083600847333b6c371/href">https://medium.com/media/3ae6a80d526c71083600847333b6c371/href</a></iframe><p>Works like a charm. When a user types their name into the text box, the text block placed below displays: “<em>Hello, %username%!</em>”. Values of these two controls stay synchronized — when the text box’s content changes, the text block updates itself immediately. Button clears the text box.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/847/1*euARNN3y9ptek5tI_iNT8g.png" /><figcaption>A simple demo app built on <a href="https://docs.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide">Universal Windows Platform</a></figcaption></figure><p>But wait! Our UI only needs two synchronized observable properties and one command, why do we have to write more than 20 lines of code to achieve that? What will happen, if we decide to add more properties representing ViewModel state? The code will bloat, becoming increasingly harder to understand and maintain!</p><h3><strong>Recipe #1. Observables. Shorter Getters And Setters. ReactiveUI</strong></h3><p>Well, the property change notifications boilerplate code issue is not new, and there are several solutions. Let’s take a look at <a href="https://reactiveui.net/">ReactiveUI</a>. It is a cross-platform, composable, functional reactive MVVM framework that brings the power of <a href="http://reactivex.io/">Reactive Extensions</a> for the .NET platform. It also provides an INotifyPropertyChanged base class named <a href="https://reactiveui.net/api/reactiveui/reactiveobject/">ReactiveObject</a> and a bunch of extension methods. Let’s modify our code snippet and see, how its reactive version looks like.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/adcccd1d429ee3b4c145d8504c30ea6a/href">https://medium.com/media/adcccd1d429ee3b4c145d8504c30ea6a/href</a></iframe><p>This snippet does exactly the same as the previous one but is shorter, more predictable, easier to understand and maintain. Property relations are described in one place using declarative <a href="https://reactiveui.net/">ReactiveUI</a> syntax. But this code is still quite verbose — we have to implement getters, setters, and backing fields explicitly.</p><h3><strong>Recipe #2. Boilerplate Code Encapsulation. Reactive Property</strong></h3><p>Another solution is to use reactive bindings from the <a href="https://github.com/runceel/ReactiveProperty">ReactiveProperty </a>library. This package provides wrapper classes responsible for sending notifications to the UI. Here ViewModel does not need to implement any interfaces, instead, each property implements INotifyPropertyChanged itself. Such properties also are observables — they can be mapped, filtered, combined, and so on. Let’s rewrite our sample using <a href="https://github.com/runceel/ReactiveProperty">ReactiveProperty</a>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f404aad26d88a458c3f0bed7fab109ca/href">https://medium.com/media/f404aad26d88a458c3f0bed7fab109ca/href</a></iframe><p>We only need to declare and initialize reactive properties and describe relations among them. No boilerplate code needed, except for property initializers. But this approach has a drawback — we should modify our XAML markup to make these bindings work as expected. Reactive properties themselves are wrappers, so UI needs to bind to each wrapper’s own property.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/350451e9f31c2c759312e153bd5d2568/href">https://medium.com/media/350451e9f31c2c759312e153bd5d2568/href</a></iframe><h3><strong>Recipe #3. Assembly Weaving. Fody + ReactiveUI</strong></h3><p>In a typical ViewModel, each property should send notifications to the UI when its value changes. With <a href="https://github.com/Fody/PropertyChanged">PropertyChanged.Fody</a> package, a developer doesn’t have to take care of this. The only requirement is a ViewModel being marked with <em>AddINotifyPropertyChangedInterface</em> attribute — and code raising the property change event will be injected into setters <em>automatically </em>during the project build. If we need to turn our properties into observables, we can always use the <a href="https://reactiveui.net/api/reactiveui/whenanymixin/">WhenAnyValue</a> extension method from <a href="https://reactiveui.net/">ReactiveUI</a>. Let’s rewrite our snippet again and see, how concise our code will become!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/77d466a419dc4236a8412afb5a1a9a9e/href">https://medium.com/media/77d466a419dc4236a8412afb5a1a9a9e/href</a></iframe><p><a href="https://github.com/Fody/Fody">Fody</a> manipulates the IL of an assembly at build time. <a href="https://github.com/Fody/PropertyChanged#overview">PropertyChanged.Fody</a> add-in searches for all classes implementing the INotifyPropertyChanged interface or marked with AddINotifyPropertyChangedInterface attribute, and modifies those classes’ property setters.</p><p>While this approach is great and allows us to write clean and simple code, outdated .NET Framework versions, including 4.5.1 and <a href="https://en.wikipedia.org/wiki/.NET_Framework_version_history#Overview">older ones</a>, are no longer supported. This means you <strong>can </strong>actually use <a href="https://github.com/Fody">Fody</a> with outdated versions but at your own risk while keeping in mind that any bugs found won’t ever get fixed. .NET Core versions are supported according to the .NET Core <a href="https://www.microsoft.com/net/Support/Policy">support policy</a>.</p><h3>Recipe #4. Assembly Weaving. ReactiveUI.Fody</h3><p>Yet another option is to use the <a href="https://www.nuget.org/packages/ReactiveUI.Fody/">ReactiveUI.Fody</a> package, which is now fully <a href="https://github.com/reactiveui/ReactiveUI/pull/1828">compatible with .NET Core</a>. It works similarly to <a href="https://github.com/Fody/PropertyChanged#overview">PropertyChanged.Fody</a>, but uses the opt-in approach — you need to mark all properties with<a href="https://github.com/reactiveui/reactiveUI/#forget-about-inotifypropertychanged-boilerplate-code"> ReactiveUI.Fody attributes</a> explicitly to have INotifyPropertyChanged boilerplate code injected into them at compile time. Additionally, this approach allows you to create get-only properties based on <a href="https://reactiveui.net/docs/handbook/oaph/">ObservableAsPropertyHelper</a> that will always contain the latest value from an observable stream. Using readonly OAPHs in your codebase for describing computed properties allows you to benefit from compile-time checks that help you to ensure that your computed properties always contain the latest value from a certain IObservable&lt;T&gt; stream.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8c3a897e0a1bef972a4dfb79741a63d4/href">https://medium.com/media/8c3a897e0a1bef972a4dfb79741a63d4/href</a></iframe><p>Hope this article helps you get started with implementing the MVVM pattern via <a href="http://reactivex.io/">Reactive Programming</a> and keeping your code clean and concise. See the <a href="https://medium.com/@worldbeater/reactive-ui-fody-cross-platform-forms-7b501d79f46b">next chapter for more examples</a>. If you are willing to learn ReactiveUI, check out the <a href="https://reactiveui.net/docs/getting-started/">Getting Started tutorial</a> and the <a href="https://reactiveui.net/docs/handbook/">ReactiveUI Handbook</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=175dc69cfc82" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>