[C#][Uno Platform] Create desktop applications on Ubuntu 1
Tags: csharp, unoplatform, ubuntu
Published: 2021-12-24 01:24:52

## Intro

This time, I will try creating desktop applications on Ubuntu 21.10.

### Environments
* Ubuntu ver.21.10
* .NET ver.6.0.101

## Selecting UI frameworks

When I create desktop applications on Windows, I can select from WPF, WinForms, MAUI, and so on.
But they aren't for creating LINUX desktop applications.

So I choose Uno Platform.

* [Uno Platform](https://platform.uno/)

## Install
### Install .NET 6

Although I can install .NET 6 from Ubuntu Software, I shall not do that.
Because it only for the super user.

I installed .NET 6 by following "Install SDK" of Ubuntu 21.10.

* [Install the .NET SDK or the .NET Runtime on Ubuntu - Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu)

### Editor(IDE)

Because I like VSCode, so I installed it from Ubuntu Software.
After installing, I added C# and Uno Platform extensions.

* [Uno Platform - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=unoplatform.vscode)

### Uno Platform

To create Uno Platform applications, I add their templates first.

```
dotnet new -i Uno.ProjectTemplates.Dotnet
```

* [dotnet new templates for Uno Platform - Uno Platform](https://platform.uno/docs/articles/get-started-dotnet-new.html)

Because I use GTK projects for creating applications for Linux, I install GTK3.

* [Additional setup for Linux - Uno Platform](https://platform.uno/docs/articles/get-started-with-linux.html)

After installing, I can check if are there any problems by uno-check.

* [Troubleshoot your environment with uno-check - Uno Platform](https://platform.uno/docs/articles/uno-check.html)

## Creating a project

I create a .NET 6 project. Because I want to create an application only for Linux(GTK), I excluded other platforms.

```
dotnet new unoapp-net6 -o UnoSample -M=false -skia-wpf=false
```

### Run
I can run the project as same as any other .NET projects.

```
dotnet run --project  UnoSample.Skia.Gtk
```

#### Result

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yf2l9fjxwq0wya66ycsh.png)

...Why is the text not displayed? 

### Displaying texts

I found warnings below.

```
warn: Windows.UI.Composition.TextVisual[0]
      The font Segoe UI could not be found, using system default
warn: Windows.UI.Xaml.UIElement[0]
      The BorderThicknessProperty dependency property does not exist on Uno.UI.Xaml.Core.RootVisual
```

I have to set the fonts.

#### MainPage.xaml
```xml
<Page
    x:Class="UnoSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UnoSample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"    
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    FontFamily="Noto Sans CJK JP">

    <StackPanel>
      <TextBlock x:Name="txt"
                  Text="Hello, world!"
                  Margin="20"
                  FontSize="30" />
      <Button Content="Update" x:Name="buttonRefresh" Margin="300 10 10 30" FontSize="16" Width="150" Height="80"/>
      </StackPanel>
</Page>
```

I also can set FontFamily from the code behind.

#### MainPage.xaml.cs
```cs
using System;
using Windows.UI.Xaml.Controls;

namespace UnoSample
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            // set FontFamily
            this.FontFamily = new FontFamily("Noto Sans CJK JP");
        }
    }
}
```

I still have another problem.
Texts of button elements are not displayed.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/841f4w0k8pxtgbf6boi2.png)

So I add "FontFamily" in each button elements.

#### MainPage.xaml
```xml
<Page
    x:Class="UnoSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UnoSample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"    
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    FontFamily="Noto Sans CJK JP">

    <StackPanel>
        <TextBlock x:Name="txt"
                    Text="Hello, world!"
                    Margin="20"
                    FontSize="30" />
        <Button Content="Update" x:Name="buttonRefresh" Margin="300 10 10 30" FontSize="16" Width="150" Height="80" FontFamily="Noto Sans CJK JP" />
    </StackPanel>
</Page>
```

#### Result

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/553djhp51kqea3p10tp5.png)

## Adding ViewModels

How to add ViewModels?

This time, I try adding them as same as WPF projects.

* [【.NET 5】【WPF】Try MVVM](https://dev.to/masanori_msl/net-5-wpf-try-mvvm-3m0e)

#### MainPage.xaml
```xml
...
    <StackPanel>
        <TextBlock x:Name="txt"
                    Text="{Binding PageTitle}"
                    Margin="20"
                    FontSize="30" />
        <Button Content="Update" x:Name="buttonRefresh" Margin="300 10 10 30" FontSize="16" Width="150" Height="80" FontFamily="Noto Sans CJK JP" />
    </StackPanel>
</Page>
```

#### MainPage.xaml.cs
```cs
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using UnoSample.ViewModels;

namespace UnoSample
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.DataContext = new MainPageViewModel();
        }
    }
}
```

#### MainPageViewModel.cs
```cs
namespace UnoSample.ViewModels
{
    public class MainPageViewModel
    {
        public string PageTitle { get; set; } = "Hello World";
        public SampleButtonClick ButtonClick { get; set; } = new SampleButtonClick();
        
        public void SampleClicked()
        {
            Console.WriteLine("AAA");
        }
    }
}
```

#### SampleButtonClick.cs
```cs
using System.Windows.Input;

namespace UnoSample.ViewModels
{
    public class SampleButtonClick: ICommand
    {
        public event EventHandler? CanExecuteChanged;
        public bool CanExecute(object? parameter)
        {
            return true;
        }
        public void Execute(object? parameter)
        {
            Console.WriteLine("Executed");
        }
    }
}
```

### Event handlers

How to add event handlers?

I couldn't bind as same as WPF.


#### MainPage.xaml
```xml
...
    <StackPanel>
...
        <!-- Error -->
        <Button Content="Update" x:Name="buttonRefresh" Margin="300 10 10 30" FontSize="16" Width="150" Height="80" FontFamily="Noto Sans CJK JP"
            Click="{Binding ButtonClick}" />
    </StackPanel>
</Page>
```

Accoring to this blog post, I call code behind first, and call methods of ViewModels from it.

* [Do Uno Mvvm? - Nick's .NET Travels](https://nicksnettravels.builttoroam.com/do-uno-mvvm/)

#### MainPage.xaml
```xml
...
    <StackPanel>
...
        <Button Content="Update" x:Name="buttonRefresh" Margin="300 10 10 30" FontSize="16" Width="150" Height="80" FontFamily="Noto Sans CJK JP"
            Click="OnClick"/>
    </StackPanel>
</Page>
```

#### MainPage.xaml.cs
```cs
...
namespace UnoSample
{
    public sealed partial class MainPage : Page
    {
...
        private void OnClick(object sender, RoutedEventArgs e)
        {
            (this.DataContext as MainPageViewModel)?.SampleClicked();
        }
    }
}
```
_**added on 2021-12-25 10:11 JST**_

I can use "ButtonClick" of ViewModel like below.

#### MainPage.xaml
```xml
...
    <StackPanel>
...
        <Button Content="Update" x:Name="buttonRefresh" Margin="300 10 10 30" FontSize="16" Width="150" Height="80" FontFamily="Noto Sans CJK JP"
                    Command="{Binding ButtonClick}"/>
    </StackPanel>
</Page>
```

* [Using C#, XAML + Uno Platform to Build One Codebase, Cross-Platform Apps - Keyhole Software](https://keyholesoftware.com/2019/08/12/using-c-xaml-uno-platform-to-build-one-codebase-cross-platform-apps/)