.NET MAUI Blazor - Best practices for Desktop UI

mhrastegari

Mohammad Hossein Rastegarinia

Posted on February 18, 2023

.NET MAUI Blazor - Best practices for Desktop UI

.NET MAUI Blazor is an open-source framework that lets you create cross-platform apps with web UI components and C# code. It uses BlazorWebView to render Razor components on mobile and desktop. So, like the last article which mostly was for mobile, this time I’m going to show you some handy tips for Desktop UI.

Disable refresh with the F5 key and zoom with the mouse wheel

In your MainPage.xaml use the Loaded event of the ContentPage tag to override BlazorWebView’s default settings like the code down below:

   public MainPage()
    {
        InitializeComponent();
        Loaded += ContentPage_Loaded;
    }

    private async void ContentPage_Loaded(object sender, EventArgs e)
    {
#if WINDOWS && RELEASE
        var webView2 = (blazorWebView.Handler.PlatformView as Microsoft.UI.Xaml.Controls.WebView2);
        await webView2.EnsureCoreWebView2Async();

        var settings = webView2.CoreWebView2.Settings;
        settings.IsZoomControlEnabled = false;
        settings.AreBrowserAcceleratorKeysEnabled = false;
#endif
    }
Enter fullscreen mode Exit fullscreen mode

Disable context menu

By default Windows context menu is disabled but macOS is not, so we need to disable it with a little bit of JavaScript in your index.html file:

window.addEventListener('contextmenu', (event) => event.preventDefault());
Enter fullscreen mode Exit fullscreen mode

Change Windows Titlebar colors

In the Platforms/Windows/App.xaml add these lines and change the colors to whatever you want.

<maui:MauiWinUIApplication
    x:Class="YouProject.Client.App.Platforms.Windows.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:maui="using:Microsoft.Maui">
    <maui:MauiWinUIApplication.Resources>
        <ResourceDictionary>
            <SolidColorBrush x:Key="WindowCaptionForeground">#512bdf</SolidColorBrush>
            <SolidColorBrush x:Key="WindowCaptionBackground">#ffffff</SolidColorBrush>
            <SolidColorBrush x:Key="WindowCaptionForegroundDisabled">#512bdf</SolidColorBrush>
            <SolidColorBrush x:Key="WindowCaptionBackgroundDisabled">#ffffff</SolidColorBrush>
        </ResourceDictionary>
    </maui:MauiWinUIApplication.Resources>
</maui:MauiWinUIApplication>
Enter fullscreen mode Exit fullscreen mode

Learn more from Microsoft documentation.

Common HTML/CSS tricks

1. Disable dragging images and selecting texts
Well, I guess we all agree that not every image should be draggable also not every text should be selected so all you need to add these:

*:not(input) {
    user-select: none;
    -webkit-user-drag: none;
    -webkit-user-select: none;
}
Enter fullscreen mode Exit fullscreen mode

2. Have some tooltips
Remember tooltips in developing desktop apps? You can do it with the title attribute on any HTML element.
For example:

<button class="close-button" title="Close" @onclick="Close()"></button>
Enter fullscreen mode Exit fullscreen mode

3. Change mouse cursor
For different elements and components the mouse cursor can be changed, here is an example of using the cursor property to change the cursor to a pointer when hovering over a div tag with the class of item:

.item {
    cursor: pointer;
}
Enter fullscreen mode Exit fullscreen mode

4. Add some active and hover effects
By default in some of the Native controls there are some hover and active(click) effects that change the color, So we can do it on the web like this:

  .item {
       background-color: white;
    }

  .item:active {
       background-color: whitesmoke;
    }

  .item:hover {
       background-color: lightgray;
    }
Enter fullscreen mode Exit fullscreen mode

Get window size

Sometimes you need to have the window size to do some calculations in your C# code so you can do it with JavaScript like this:

In your Razor component add these lines of code

public partial class YourComponent : ComponentBase
{
    public int WindowWidth { get; set; }
    private string _resizeEventListenerId = string.Empty;
    private DotNetObjectReference<YourComponent>? _dotnetObjectReference;

    [Inject] private IJSRuntime JSRuntime { get; set; } = default!;

    protected override async Task OnInitializedAsync()
    {
        _dotnetObjectReference = DotNetObjectReference.Create(this);
        await base.OnInitializedAsync();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeVoidAsync("UpdateWindowWidth", _dotnetObjectReference);
            await InitWindowWidthListener();
        }

        await base.OnAfterRenderAsync(firstRender);
    }

    [JSInvokable]
    public void UpdateWindowWidth(int windowWidth)
    {
        WindowWidth = windowWidth;
        StateHasChanged();
    }

    private async Task InitWindowWidthListener()
    {
        _resizeEventListenerId = Guid.NewGuid().ToString();
        await JSRuntime.InvokeVoidAsync("AddWindowWidthListener", _dotnetObjectReference, _resizeEventListenerId);
    }
}


Enter fullscreen mode Exit fullscreen mode

And put these in a JavaScript file and add it in your index.html

let windowEventListeners = {};

function AddWindowWidthListener(objReference, id) {
    let eventListener = () => UpdateWindowWidth(objReference);
    window.addEventListener("resize", eventListener);
    windowEventListeners[id] = eventListener;
}

function RemoveWindowWidthListener(id) {
    window.removeEventListener("resize", windowEventListeners[id]);
    delete windowEventListeners[id];
}

function UpdateWindowWidth(objReference) {
    objReference.invokeMethodAsync("UpdateWindowWidth", window.innerWidth);
}
Enter fullscreen mode Exit fullscreen mode

Well, I guess it would be better to have both Mobile and Desktop best practices in one project, So I updated the sample repo containing all of the code that we discussed. You can have it from here.

Happy coding ;D

💖 💪 🙅 🚩
mhrastegari
Mohammad Hossein Rastegarinia

Posted on February 18, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related