<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Konrad Müller</title>
    <description>The latest articles on DEV Community by Konrad Müller (@krdmllr).</description>
    <link>https://dev.to/krdmllr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F141481%2F8c590c8a-2298-46d5-bcbf-55626d68252d.jpeg</url>
      <title>DEV Community: Konrad Müller</title>
      <link>https://dev.to/krdmllr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/krdmllr"/>
    <language>en</language>
    <item>
      <title>Using Microcharts with .NET MAUI</title>
      <dc:creator>Konrad Müller</dc:creator>
      <pubDate>Sat, 28 May 2022 13:12:37 +0000</pubDate>
      <link>https://dev.to/krdmllr/using-microcharts-with-net-maui-3515</link>
      <guid>https://dev.to/krdmllr/using-microcharts-with-net-maui-3515</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/microcharts-dotnet/Microcharts" rel="noopener noreferrer"&gt;Microcharts&lt;/a&gt; is one of the most well-known open source charting libraries for Xamarin and many people, including me, would like to use it with .NET MAUI. Work on .NET MAUI support by Microcharts should arrive soon but while the &lt;a href="https://github.com/microcharts-dotnet/Microcharts/pull/280" rel="noopener noreferrer"&gt;PR is not merged&lt;/a&gt;, I want to show how to already use Microcharts with .NET MAUI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/krdmllr/Microcharts.MAUI.Sample" rel="noopener noreferrer"&gt;You can find a sample for this on GitHub.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the required packages
&lt;/h2&gt;

&lt;p&gt;First thing to do is to add all required packages. We need Microcharts, which will bring in the rendering logic.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

dotnet add package Microcharts --version 0.9.5.9


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Additionally, we need a reference to SkiaSharp controls for .NET MAUI.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

dotnet add package SkiaSharp.Views.Maui.Controls --version 2.88.0


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can also just add the references directly to the &lt;code&gt;.csproj&lt;/code&gt; file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;

    &lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"Microcharts"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"0.9.5.9"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"SkiaSharp.Views.Maui.Controls"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"2.88.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Adding the ChartView
&lt;/h2&gt;

&lt;p&gt;Microcharts has a smart structure that uses one shared code base that provides the rendering, based on SkiaSharp. The platforms just provide a SkiaSharp view and use this base layer to handle drawing events. We can therefore basically copy the &lt;a href="https://github.com/microcharts-dotnet/Microcharts/blob/main/Sources/Microcharts.Forms/ChartView.cs" rel="noopener noreferrer"&gt;Xamarin.Forms implementation of the view&lt;/a&gt; and slightly adapt it.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChartView&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SKCanvasView&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;EventHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SKPaintSurfaceEventArgs&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ChartPainted&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;BindableProperty&lt;/span&gt; &lt;span class="n"&gt;ChartProperty&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BindableProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChartView&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;propertyChanged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OnChartChanged&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Chart&lt;/span&gt; &lt;span class="n"&gt;Chart&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChartProperty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;SetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChartProperty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;InvalidatedWeakEventHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ChartView&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Chart&lt;/span&gt; &lt;span class="n"&gt;_chart&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ChartView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;BackgroundColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;PaintSurface&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnPaintCanvas&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnChartChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BindableObject&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;oldValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ChartView&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_chart&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_chart&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InvalidateSurface&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_chart&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_chart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ObserveInvalidate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InvalidateSurface&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnPaintCanvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SKPaintSurfaceEventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_chart&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;_chart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Surface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Surface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Clear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SKColors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Transparent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;ChartPainted&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This view basically subscribes to drawing events and handles them by calling the Microcharts Chart drawing logic on the canvas ( &lt;code&gt;_chart.Draw(e.Surface.Canvas, e.Info.Width, e.Info.Height)&lt;/code&gt; ). Just drop it in your project and you can now reference it from your views.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Before finally using it, we just need to add the required handlers by adding the &lt;code&gt;.UseSkiaSharp()&lt;/code&gt; method to our MAUI builder in the &lt;code&gt;MauiProgram.cs&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MauiApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseMauiApp&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSkiaSharp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can now use the ChartView as you would use with Microcharts in any other project:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ContentPage&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;xmlns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;microcharts&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"clr-namespace:Microcharts.MAUI.Sample;assembly=Microcharts.MAUI.Sample"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;microcharts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ChartView&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Chart"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;ContentPage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Read more about Microcharts usage in &lt;a href="https://github.com/microcharts-dotnet/Microcharts/wiki" rel="noopener noreferrer"&gt;their documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foujcw9wm29vqb7kdhl9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foujcw9wm29vqb7kdhl9f.png" alt="Chart sample on Android"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbw1yukiopesz0s5ylu2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbw1yukiopesz0s5ylu2b.png" alt="Chart sample on Windows"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Setting up a Xamarin.Forms WPF backend on .NET Core</title>
      <dc:creator>Konrad Müller</dc:creator>
      <pubDate>Sat, 23 May 2020 11:48:52 +0000</pubDate>
      <link>https://dev.to/krdmllr/setting-up-a-xamarin-forms-wpf-backend-on-net-core-109l</link>
      <guid>https://dev.to/krdmllr/setting-up-a-xamarin-forms-wpf-backend-on-net-core-109l</guid>
      <description>&lt;p&gt;&lt;em&gt;TLDR: You can now build Xamarin.Forms WPF applications on .NET Core, you can find a sample &lt;a href="https://github.com/krdmllr/DotNetDesktopSamples/tree/master/Xamarin.Forms/FormsDesktop.WPF"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Xamarin.Forms supports a wide variety of platforms, so called platform backends. Some of these are iOS, Android, macOS, UWP, GTK or WPF. While the WPF implementation was running on the old .NET Framework WPF version, in april support for .NET Core was merged. This post will show you how to add the WPF backend to your existing Xamarin.Forms project and what opportunities this brings. I will use Visual Studio as reference but you can do all of the steps and run the application using the dotnet CLI and any editor you want!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: If you want to target Windows with your application, you should generally use the UWP backend since its the stable and an officially supported backend. If you are sure you want to use WPF, go ahead!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://visualstudio.microsoft.com/en/downloads/"&gt;Visual Studio 2019&lt;/a&gt; (Windows) 16.5 with the Xamarin, .NET Desktop and .NET Core workloads installed&lt;/li&gt;
&lt;li&gt;The latest &lt;a href="https://dotnet.microsoft.com/download"&gt;.NET Core SDK&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A Xamarin.Forms project you want to add the WPF backend to, I will use my FormsDesktop project from my &lt;a href="https://github.com/krdmllr/DotNetDesktopSamples"&gt;.NET desktop framework sample collection&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My sample project before the WPF backend is added looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B8UA2ksb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ze0yn06e8vl1j2prox43.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B8UA2ksb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ze0yn06e8vl1j2prox43.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the WPF .NET Core project
&lt;/h2&gt;

&lt;p&gt;Start of by adding a new WPF App (.NET Core) to your solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tvgLuO1b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z7b2hm6ifymdyxevkxpz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tvgLuO1b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z7b2hm6ifymdyxevkxpz.png" alt="Visual Studio new project explorer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to use the CLI you can use the command &lt;code&gt;dotnet new wpf -n PROJECTNAME.WPF&lt;/code&gt;&lt;br&gt;
We now have to modify the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a reference to the shared project in your solution, in my sample that would be the "FormsDesktop" project. The CLI command from inside the WPF project folder would be &lt;code&gt;dotnet add reference ../FormsDesktop&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add the latest &lt;code&gt;Xamarin.Forms.Platform.WPF&lt;/code&gt; NuGet package to the WPF project and make sure it has the same version as the Xamarin.Forms references in your other projects. You can use the NuGet manager in Visual Studio or the command &lt;code&gt;dotnet add package Xamarin.Forms.Platform.WPF&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open the .csproj file of the WPF project and add the following lines:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ItemGroup&amp;gt; 
 &amp;lt;EmbeddedResource Remove="**\*.xaml" /&amp;gt; 
&amp;lt;/ItemGroup&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is a workaround for a bug when working with xaml files which would lead to unresolvable build errors.&lt;/p&gt;

&lt;p&gt;After these steps, your .csproj file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"&amp;gt;

  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;OutputType&amp;gt;WinExe&amp;lt;/OutputType&amp;gt;
    &amp;lt;TargetFramework&amp;gt;netcoreapp3.1&amp;lt;/TargetFramework&amp;gt;
    &amp;lt;UseWPF&amp;gt;true&amp;lt;/UseWPF&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;EmbeddedResource Remove="**\*.xaml" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;PackageReference Include="Xamarin.Forms.Platform.WPF" Version="4.6.0.772" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;ProjectReference Include="..\FormsDesktop\FormsDesktop.csproj" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

&amp;lt;/Project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Initializing the Xamarin.Forms application
&lt;/h2&gt;

&lt;p&gt;After adding the project all we have to do is to initialize the Xamarin.Forms application when starting the WPF application.&lt;br&gt;
The &lt;code&gt;MainWindow&lt;/code&gt; is by default the window that is initially loaded when the application is started. Start with the &lt;code&gt;.xaml&lt;/code&gt; file and add a reference to the &lt;code&gt;Xamarin.Forms.WPFnamespacexmlns:wpf=clr-namespace:Xamarin.Forms.Platform.WPF;assembly=Xamarin.Forms.Platform.WPF&lt;/code&gt;. Then change the class from &lt;code&gt;Window&lt;/code&gt;to &lt;code&gt;wpf:FormsApplicationPage&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;wpf:FormsApplicationPage x:Class="Xamarin.Forms.WPF.MainWindow"
                          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                          xmlns:local="clr-namespace:Xamarin.Forms.WPF"
                          xmlns:wpf="clr-namespace:Xamarin.Forms.Platform.WPF;assembly=Xamarin.Forms.Platform.WPF"
                          mc:Ignorable="d"
                          Title="WPF .NET Core" Height="450" Width="800"&amp;gt; 
&amp;lt;/wpf:FormsApplicationPage&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Continue with the &lt;code&gt;MainWindow.xaml.cs&lt;/code&gt; file where the Xamarin.Forms framework is initialized and the application is loaded as content of the WPF application. To do this, add the Xamarin.Forms initialization &lt;code&gt;Forms.Init()&lt;/code&gt; and the application load &lt;code&gt;LoadApplication(new SharedProject.App())&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace Xamarin.Forms.WPF
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            Forms.Init();
            LoadApplication(new FormsDesktop.App());
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Run it!
&lt;/h2&gt;

&lt;p&gt;You can now run the WPF application directly from Visual Studio or the CLI with the &lt;code&gt;dotnet run&lt;/code&gt; command. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Af3bvUhS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hojwms2pskd4n3jdml4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Af3bvUhS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hojwms2pskd4n3jdml4x.png" alt="The running application&amp;lt;br&amp;gt;
"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing the application
&lt;/h2&gt;

&lt;p&gt;Once the application runs we just have to publish it to ship it to some user. Like any .NET Core application, you can just publish it from Visual Studio (right click the project - publish) or use the CLI with &lt;code&gt;dotnet publish -c Release&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rp1ovQVh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4skforhdohv2tx9hqtjm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rp1ovQVh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4skforhdohv2tx9hqtjm.png" alt="Visual Studio configure publishing window"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the great benefits of .NET Core come into play. Old WPF projects that build on the .NET framework always required the correct .NET runtime on the users device. With .NET Core, you can publish the application self contained which will ship the runtime with the application! Its just a drop down in Visual Studio (&lt;em&gt;Deployment Mode&lt;/em&gt;) or a switch in the publishing command &lt;code&gt;-r win10-x86&lt;/code&gt;. There are more runtime identifers available for specific windows versions, you can find them &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/rid-catalog#windows-rids"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next up, instead of shipping a huge folder with hundreds of files, we can create a single executable by selecting &lt;em&gt;Produce single file&lt;/em&gt; in Visual Studio or the &lt;code&gt;-p:PublishSingleFile=true&lt;/code&gt; switch.&lt;/p&gt;

&lt;p&gt;Last but not least, &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/deploying/trim-self-contained"&gt;.NET Core is now capable of tree shaking&lt;/a&gt; to reduce the size of the published application with the &lt;em&gt;Trim unused assemblies&lt;/em&gt; setting or the &lt;code&gt;-p:PublishTrimmed=true&lt;/code&gt; switch. This will reduce an empty application from 140 to around 90mb. Just be aware that this feature is still in preview and like linking Android and iOS applications, you have to make sure that no assembly is removed that is only used by reflection.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's a wrap
&lt;/h2&gt;

&lt;p&gt;This article showed how to add a WPF backend to your Xamarin.Forms project that is targeting .NET Core and some of the benefits this brings, like working and running from the dotnet CLI, tree shaking, self contained or single executable deployments. If you have any further questions dont hesitate to reach out to me on &lt;a href="https://twitter.com/konmue"&gt;Twitter&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>xamarinforms</category>
      <category>netcore</category>
      <category>dotnet</category>
      <category>wpf</category>
    </item>
  </channel>
</rss>
