[C#][Uno Platform] Create desktop applications on Ubuntu 1

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.

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.

Editor(IDE)

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

Uno Platform

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

dotnet new -i Uno.ProjectTemplates.Dotnet

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

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

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

...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

<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

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.

So I add "FontFamily" in each button elements.

MainPage.xaml

<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

Adding ViewModels

How to add ViewModels?

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

MainPage.xaml

...
    <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

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

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

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

...
    <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.

MainPage.xaml

...
    <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

...
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

...
    <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>

24