Blazor Hybrid (MAUI) - Customize TitleBar

Humberto Cruz-Oyola Jr 21 Reputation points
2022-07-07T19:02:56.817+00:00

This is a follow-up to a previous question. I now see that the Title Bar customization API only works for Windows 11 (AppWindow.TitleBar is null on <Windows 11). For this question, keep in mind that I am only asking about the Title Bar when targeting Windows.

The Question

Simply put, how do I provide a custom title bar in a Blazor Hybrid application when targeting Windows, such that it responds to color changes that are triggered by events at runtime?

More information

I am struggling to customize the title bar of a Blazor Hybrid application for targeting Windows <11. I have successfully been able to use the Title Bar customization API to change the background color and title (since the background color should respond to theme changes in the Razor Class Library where there is more than just a light and dark theme). I have also see the Title bar customization article in the Microsoft Learn. I've also attempted to integrate portions of this issue and this project, but I lose the title bar drag zone and/or lose the ability to change the color at runtime.

I am looking for a an example of a customizable title bar that uses a new MAUI Blazor app (since it does not get AppShell nor MainWindow) that works with at Windows 10 (or before even, if that's possible). My current theme-responsive demo is on my github and the functionality can be seen when running it on a Windows 11 machine. The optimal example for me would be a fork of this project with the customizable toolbar added such that the application behaves the same in Windows 10 and Windows 11, while still be able to be run on the other Platforms. I am also not considering MacOS at the moment, but that would be a plus, but absolutely not necessary.

I appreciate your time and any help you can provide!

Update/Edit

2022-07-20

I am still struggling with the different approaches to customizing the title bar in a MAUI application when targeting Windows, specifically when running it on Windows 10. I've tried various approaches and I can switch out the main window on launch, but can't add the BlazorWebView as content to the MainWindow; or I can change the background color of the title bar and caption buttons, but lose the title icon and text since it seems like I am adding a border to the non-client area of the window that covers up the original title bar; or (I haven't been able to do this again, but know I did it once) I can use a Data Template and the ExtendsContentIntoTitleBar and SetTitleBar(null) approach to have the app bleed into the non-client area. I am sure there is just something I don't know/understand how to do that someone who has prior experience with WPF would know.

Here is an example of the closest I got to it working where I can change the color of the title bar (and I think I know which dictionary entries to overwrite to get the button background color, foreground color, and pointer over colors to cooperate). As you can see, I lose the title bar text (except when the title bar is inactive) and I can't make the title bar repaint in the handler for the PropertyChanged event on my PreferencesState class. This is the latest version of the solution I've been working with.

The point is that I would love to either have someone work with me to help guide me in the right direction, or show an example of customizing the Title Bar (like the WinUI example) in a new (as in File -> New -> Project -> .NET MAUI Blazor App such that when targeting Windows (and using a BlazorWebView control for the main page content), we get the custom title bar with Icon, Title Text, Background Color, Inactive Background Color, Control Caption Button Background Color, Control Caption Button Foreground Color, Control Caption Button Pointer Over color, and anything else that might seem relevant for customizing the non-client area. I know this is possible because, as I understand it, Visual Studio is in large part a WPF application. The menu bar is in the non-client area, along with other interactable controls. When you change the color theme, the color applies to all borders, as well as the text forecolor (and even the icon color).

Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,567 questions
Windows App SDK
Windows App SDK
A set of Microsoft open-source libraries, frameworks, components, and tools to be used in apps to access Windows platform functionality on many versions of Windows. Previously known as Project Reunion.
783 questions
.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,450 questions
{count} votes

3 answers

Sort by: Most helpful
  1. Humberto Cruz-Oyola Jr 21 Reputation points
    2022-10-07T16:29:06.643+00:00

    Hmm. Simple? I'm not sure whather I can call this simple or not. It's been a couple of months since I looked at this and I've been to a very busy work state. In any case, I do have a repo with different approaches. Iirc, the win11-ftw is the straightforward approach using the Title Bar customization API, but I can't remember what the master branch had in it. One of my YouTube videos (one1lion on YouTube) shows me struggling with it. I'm sure one of them even shows it working in a way that should also work on Win 10. Again, it's been a bit and I am not currently able to search for it, but wanted to at least respond to you. Hopefully one of those sources, along with the other references in this post will help. I will be revisiting it when my current client's product brings me back to customizing the native window, but at the moment, that effort has been suspended.

    0 comments No comments

  2. Péter Hazai 36 Reputation points
    2022-10-10T06:46:47.183+00:00

    I am on windows 10, and many of our customers use this operation system, so we need to support that. I currently doing a research on switching from WPF to MAUI, and I would like to replicate the current UI status in this framework. I looked at your repository before I asked the question but went into a few different troubles unfortunately.
    Basicly I can narrow down the different trys into to two ways:

    • first I tried James's suggestion, the OnWindowCreated lifecycle event. The "del" parameter is of type MauiWinUIWindow which is a descendant of Microsoft.UI.Xaml.Window, and this is great. This has the needed properties and methods to apply the custom titlebar changes (actually has a method that takes UIElement to set the title bar to a custom xaml), but it simply does not work, nothing happens after the method call SetTitleBar(UIElement).
    • second try what I found in your repository, where I retrieve the Window handle through interop calls from the Application current window (which is a type of Microsoft.Maui.Controls.Window, and it is not a descendant of the Xaml Window mentioned earlier). This handle then used to retrieve the AppWindow object, and has few methods to operate the window's look, but as the documentation says it only works on windows 11. Few methods do work though, like Maximize() Minimize() etc.

    I even tried to create the window manually, but then I got two windows, one with the original blazor site, and another with no content in it, but the title bar has changed according to my custom xaml, but unfortunately I wasn't able to put the basic content into the new window, nor to get rid of the first default window and hot reload didnt event work with the second window.

    I am not sure what I am missing here, I will try out few things I have in mind and also will look into your youtube video as well.
    Thanks for your quick answer!


  3. Péter Hazai 36 Reputation points
    2022-10-13T14:02:10.253+00:00

    I made some progress, but I could not explain the results.
    My goal is to replace the title bar with a custom control, so I have total control over the looks. (Best would be to get rid of it completely and just create blazor component for the titlebar)
    So since this is windows platform specific, I was looking for some windows only solution. Every Maui component or View rather has a PlatformView property of type object. This could be anything, depending on the platform, this case of windows is FrameworkElement. So far so good. So I created on the MainPage a Grid, give some background, and retrieve the platform view of it and provided for the SetTitleBar() method as an input parameter. And it somewhat worked:

    250028-maui-custom-title-bar-on-mainpage.jpg

    I even tried to create a custom maui view with a custom handler for windows platform, and created Microsoft.UI.Xaml.Control.Grid and so on controls in it, to provide the window with "authentic" framework elements, but got the same result as above (Although I could not set the Grid's background color from code behind, at least it did not have any effect on the view, but other than that it was the same).

    On the other hand, if I override platform specific App.xaml.cs CreateWindow method and I create a new Window class (e.g. called MainWindow) which I derived from the MauiWinUIWindow class (which gets instantiated during the application startup by default), I got different results. I created a Grid in the MainWindow.xaml with same settings as on the MainPage (different text though) and after window creation, I applied the titlebar to the new window, I got perfect results:

    250046-maui-custom-title-bar-on-mainwindow.jpg

    This is what I would expect from the MainPage window as well, unfortunately it looks like I am still missing something. The top title bar does not get overridden rather appended by the provided custom control, on the other hand with the MainWindow it works perfectly but creates a new window with no blazor content in it (of course) and you can see the original MainPage in the background from the first MainPage window.

    I am not sure where to go further with this. I start to think this is a Maui framework bug. Do you have any suggestion what I should try as well? Thanks in advance!


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.