Skip to content

Instantly share code, notes, and snippets.

@LanceMcCarthy
Last active January 25, 2024 21:33
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LanceMcCarthy/4954ab92ca44c19eb4316d9d683efd50 to your computer and use it in GitHub Desktop.
Save LanceMcCarthy/4954ab92ca44c19eb4316d9d683efd50 to your computer and use it in GitHub Desktop.
Mica support in .NET MAUI
// ************************************************************************ //
// This implementation is inspired from the official WinUI3 backdrops examples
// https://github.com/microsoft/WinUI-Gallery/blob/winui3/XamlControlsGallery/ControlPagesSampleCode/SystemBackdrops/SystemBackdropsSample2.txt
// *********************************************************************** //
using Microsoft.Maui.LifecycleEvents;
#if WINDOWS10_0_17763_0_OR_GREATER
// The namespace of where the WindowsHelpers class resides
// In older versions of .NET MAUI, this was
//using YOUR_APP.Platforms.Windows
// In newer versions of .NET MAUI, it is now
using YOUR_APP.WinUI;
#endif
namespace YOUR_APP.Maui
{
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
// **** THIS SECTION IS WHAT IS RELEVANT FOR YOU ************ //
builder.ConfigureLifecycleEvents(events =>
{
#if WINDOWS10_0_17763_0_OR_GREATER
events.AddWindows(wndLifeCycleBuilder =>
{
wndLifeCycleBuilder.OnWindowCreated(window =>
{
window.TryMicaOrAcrylic(); // requires 'using YOUR_APP.WinUI;'
});
});
#endif
});
// ************* END OF RELEVANT SECTION *********** //
return builder.Build();
}
}
}
// **************************************************** //
// Place this class file in your Platforms/Windows folder
// **************************************************** //
using Microsoft.UI.Composition;
using Microsoft.UI.Composition.SystemBackdrops;
using Microsoft.UI.Xaml;
using WinRT;
namespace YOUR_APP.Platforms.Windows
{
public static class WindowHelpers
{
public static void TryMicaOrAcrylic(this Microsoft.UI.Xaml.Window window)
{
var dispatcherQueueHelper = new WindowsSystemDispatcherQueueHelper(); // in Platforms.Windows folder
dispatcherQueueHelper.EnsureWindowsSystemDispatcherQueueController();
// Hooking up the policy object
var configurationSource = new SystemBackdropConfiguration();
configurationSource.IsInputActive = true;
switch (((FrameworkElement)window.Content).ActualTheme)
{
case ElementTheme.Dark:
configurationSource.Theme = SystemBackdropTheme.Dark;
break;
case ElementTheme.Light:
configurationSource.Theme = SystemBackdropTheme.Light;
break;
case ElementTheme.Default:
configurationSource.Theme = SystemBackdropTheme.Default;
break;
}
// Let's try Mica first
if (MicaController.IsSupported())
{
var micaController = new MicaController();
micaController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>());
micaController.SetSystemBackdropConfiguration(configurationSource);
window.Activated += (object sender, WindowActivatedEventArgs args) =>
{
if (args.WindowActivationState is WindowActivationState.CodeActivated or WindowActivationState.PointerActivated)
{
// Handle situation where a window is activated and placed on top of other active windows.
if (micaController == null)
{
micaController = new MicaController();
micaController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>()); // Requires 'using WinRT;'
micaController.SetSystemBackdropConfiguration(configurationSource);
}
if (configurationSource != null)
configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated;
}
};
window.Closed += (object sender, WindowEventArgs args) =>
{
if (micaController != null)
{
micaController.Dispose();
micaController = null;
}
configurationSource = null;
};
}
// If no Mica, maybe we can use Acrylic instead
else if (DesktopAcrylicController.IsSupported())
{
var acrylicController = new DesktopAcrylicController();
acrylicController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>());
acrylicController.SetSystemBackdropConfiguration(configurationSource);
window.Activated += (object sender, WindowActivatedEventArgs args) =>
{
if (args.WindowActivationState is WindowActivationState.CodeActivated or WindowActivationState.PointerActivated)
{
// Handle situation where a window is activated and placed on top of other active windows.
if (acrylicController == null)
{
acrylicController = new DesktopAcrylicController();
acrylicController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>()); // Requires 'using WinRT;'
acrylicController.SetSystemBackdropConfiguration(configurationSource);
}
}
if (configurationSource != null)
configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated;
};
window.Closed += (object sender, WindowEventArgs args) =>
{
if (acrylicController != null)
{
acrylicController.Dispose();
acrylicController = null;
}
configurationSource = null;
};
}
}
}
}
// **************************************************** //
// Place this class file in your Platforms/Windows folder
// **************************************************** //
using System.Runtime.InteropServices;
using Windows.System; // Required for DllImport attribute and DispatcherQueue
namespace YOUR_APP.Maui.Platforms.Windows;
public class WindowsSystemDispatcherQueueHelper
{
[StructLayout(LayoutKind.Sequential)]
struct DispatcherQueueOptions
{
internal int dwSize;
internal int threadType;
internal int apartmentType;
}
[DllImport("CoreMessaging.dll")]
private static extern int CreateDispatcherQueueController([In] DispatcherQueueOptions options, [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object dispatcherQueueController);
object m_dispatcherQueueController = null;
public void EnsureWindowsSystemDispatcherQueueController()
{
if (DispatcherQueue.GetForCurrentThread() != null)
{
// one already exists, so we'll just use it.
return;
}
if (m_dispatcherQueueController == null)
{
DispatcherQueueOptions options;
options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
options.threadType = 2; // DQTYPE_THREAD_CURRENT
options.apartmentType = 2; // DQTAT_COM_STA
CreateDispatcherQueueController(options, ref m_dispatcherQueueController);
}
}
}
@Seanwanq
Copy link

Seanwanq commented Aug 5, 2022

Hi, Lance,

I gradually understand this! It seems that Styles.xaml and Colors.xaml are like .css files in html: <Style></Style> blocks are classes, and 'x:Name' is class name. Without the name, the style will be implemented to all widgets in the same type.

However, I still meet some problems that I cannot understand clearly. After I followed your instructions, I have encountered some problems:

Figure 1 The left side app activated
image

Figure 2 The right side app activated
image

As we can see, it seems that the MAUI app has a little Mica effect applied to the background, but it is much whiter than WinUI 3 app. I have commented Styles.xaml in App.xaml, and tried to comment Colors.xaml, but that's not useful. I guess the cause of this effect is WindowHelpers.cs, which is different from the WinUI 3 implementation, but as I don't understand the code clearly, I'm not sure about this.

Figure 3 A screenshot of WinUI 3 Gallary
image

Thanks a lot!

@Seanwanq
Copy link

Seanwanq commented Aug 5, 2022

Sorry, I have not noticed your example. As it is very late in my country, I will explore your example tomorrow. My appreciation.

@Seanwanq
Copy link

Seanwanq commented Aug 6, 2022

Thanks! I have read your example, which inspires me a lot! @LanceMcCarthy

@veikkoeeva
Copy link

I was also just looking this, while also looking how to create color tokens in Fluent Design (+ Mica/Acrylic style). It might be useful for others to know that at least at this moment it appears WinUI 3 does not support Acrylic on Windows 10. See microsoft/microsoft-ui-xaml#7112, microsoft/WindowsAppSDK#2463, microsoft/microsoft-ui-xaml#7061 and maybe some others too.

@LanceMcCarthy
Copy link
Author

@veikkoeeva Correct. Mica is a Windows 11 only feature, rather than a WinUI feature.

That's why my helper class above will fall back on using Acrylic if the app is running on Windows 10. That way, the app gets something from the OS, regardless of where it's running.

@veikkoeeva
Copy link

veikkoeeva commented Aug 6, 2022

@LanceMcCarthy Maybe I phrased badly, it appears Acrylic on Windows 10 is not supported by the WinUI 3 SDK. At the moment at least.

@LanceMcCarthy
Copy link
Author

@LanceMcCarthy Maybe I phrased badly, it appears Acrylic on Windows 10 is not supported either by the WinUI 3 SDK. At the moment at least.

Ah, that's different :) and unfortunate :( I have some contacts on the WinUI dev team, maybe I can get some clarifications to set our expectations. If there's anything I can share publicly, I will come back here.

@veikkoeeva
Copy link

veikkoeeva commented Aug 6, 2022

@LanceMcCarthy Indeed unfortune. It begs the question if one should ignore thinking it with limited time to use. I would not like to do that, but weekends last only for so long. :)

This is related, and I hate to bother you, but would you know a good source or a hint where to look at instructions, or a prescription, on how to create colour tokens that adhere to Fluid Design (Mica or Acrylic)?

I have discovered Fluent XAML Editor, but it looks a bit obsolete. In any event, Fluent Theme Editor (maybe I can take a subset of those "semanti slots" and do someting in XAML with them) makes better looking UIs, but unfotunately doesn't produce XAML (I'm a bit n00b).

That being written, this was actually how I ended up here. And explicitly, since you seem almost too a jovial kind of a person, don't sweat on me about this (you don't even have those "get a coffee buttons".) I've asked this color at https://docs.microsoft.com/en-us/answers/questions/957293/how-to-implement-fluid-design-colorstokens-in-xaml.html (and there's a link to Stack Overflow too). Maybe this interesting to anyone lurking in Internet and thinking about this.

@LanceMcCarthy
Copy link
Author

LanceMcCarthy commented Aug 6, 2022

I'm not sure what you mean by "token", in .NET that typically related to encryption or authentication. If I had to make an educated guess, you're meaning color or theme palettes?

forgive me if you already know what I'm about to explain, but I thought it would be good to visit/revisit. If you have any further questions or need help, I highly recommend going to the Windows Dev Discord, here's my invite link: https://discord.gg/uwp

In XAML, you just create a resource and give it a name and a value. It's really just a Key/Value pair. The Key is a string (the name) and the value is the item the x:Key is for.

Here's an example where I create an int with the key "MinFontSize"

<Int32 x:Key="MinFontSize">15</Int32>

Now I can use that anywhere in the app by using "StaticResource" (or DynamicResource if you expect it to change at runtime):

<TextBlock Text="Hello World" FontSize="{StaticResource MinFontSize}" />

That also works for any object type, like colors:

<SolidColorBrush x:Key="MyColorName" Color="MyColorValue" />

For example, that Fluent Theme Editor looks really good for styles that adhere to Fluent design. Yes, it exports as json or typescript, but you can easily create your own XAML styles with it. If you want to implement it, you just create the key/value pair in the XAML (specifically in the Resource section of the app or page).

In the exported typeScript from the fluent editor, it produced:

const myTheme = createTheme({
  palette: {
    themePrimary: '#9400d4',
    themeLighterAlt: '#faf3fd',
    themeLighter: '#ecd0f8',
... etc
  }});

So, the XAML equivalent is the following:

<Application (or Page)>
    <Application.Resources>
        <SolidColorBrush x:Key="ThemePrimary" Color="#9400d4" />
        <SolidColorBrush x:Key="ThemeLighterAlt" Color="#faf3fd" />
        <SolidColorBrush x:Key="ThemeLighter" Color="#ecd0f8" />
        ... etc
    </Application.Resources>
</Application>

A better way to do it is create a separate file that is its own ResourceDictionary file with the name of the theme. Then you merge it into the main app. The advantage of do this is you can dynamically swap it out at runtime.

This is a file named "PurpleTheme.xaml"...

<ResourceDictionary ...>
        <SolidColorBrush x:Key="ThemePrimary" Color="#9400d4" />
        <SolidColorBrush x:Key="ThemeLighterAlt" Color="#faf3fd" />
        <SolidColorBrush x:Key="ThemeLighter" Color="#ecd0f8" />

</ResourceDictionary/>

In the App.xaml, you'd merge it into the app's existing resource using the "MergedDictionaries" collection:

<Application (or Page)>
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
               <ResourceDictionary Source="MyPurpleTheme.xaml" />
            </ResourceDictionary.MergedDictionaries>

            <!-- you can put other resources that are not needed inside a theme here-->
            <Int32 x:Key="MinFontSize">15</Int32>
             ... etc
    </Application.Resources>
</Application>

Regardless of which approach you use: a single theme with all your tokens/palettes, or multiple themes in multiple ResourceDictionary files, you can just set the UI element's color properties to the x:Key.

<Button Content="Click Me" Foreground="{StaticResource ThemeLighter}" Background="{StaticResource ThemePrimary}" />

What I'm eventually getting to is that you can use that online Fluent UI Theme Designer site to generate all the "tokens" you want, it has the name and the value you already want. To being them into XAML you just need to create an item in your app resources for that thing. In the case of colors, use SolidColorBrush.

@veikkoeeva
Copy link

veikkoeeva commented Aug 6, 2022

@LanceMcCarthy Thanks! Your writing makes sense, corroborates what I was thinking to do. Using the bit outdated Fluent Editor has these

Windows10version1809:ColorPaletteResources Accent="#FFCC4D11" AltHigh="#FF000000" AltLow="#FF000000" AltMedium="#FF000000" AltMediumHigh="#FF000000" AltMediumLow="#FF000000" BaseHigh="#FFFFFFFF" BaseLow="#FF2F7BAD" BaseMedium="#FF8DBFDF" BaseMediumHigh="#FFA5D0EC" BaseMediumLow="#FF5E9DC6" ChromeAltLow="#FFA5D0EC" ChromeBlackHigh="#FF000000" ChromeBlackLow="#FFA5D0EC" ChromeBlackMedium="#FF000000" ChromeBlackMediumLow="#FF000000" ChromeDisabledHigh="#FF2F7BAD" ChromeDisabledLow="#FF8DBFDF" ChromeGray="#FF76AED3" ChromeHigh="#FF76AED3" ChromeLow="#FF093B73" ChromeMedium="#FF134B82" ChromeMediumLow="#FF266B9F" ChromeWhite="#FFFFFFFF" ListLow="#FF134B82" ListMedium="#FF2F7BAD" />
                <ResourceDictionary>
                    <BelowWindows10version1809:Color x:Key="SystemAccentColor">#FFCC4D11</BelowWindows10version1809:Color>

and things like <AcrylicBrush x:Key="SystemControlAcrylicWindowBrush" BackgroundSource="HostBackdrop" TintColor="{ThemeResource SystemChromeAltHighColor}" TintOpacity="0.8" FallbackColor="{ThemeResource SystemChromeMediumColor}" />

I have been reading about these today as I've been a bit confused about these. Here is e.g. AcrylicBrush that led me to think more about Acrylic and Mica on Windows and not defining just colors.

I suppose this goes that should I want the application overrides settings the user has chosen or not. Also if and how respect light, dark and high contrast settings. And them map those appropriately to XAML controls. In my case just for Windows, I plan to try to use Material on Android, but that's another problem. :)

Thanks for the link, I lurk a bit on UWP Discord. I'm on .NET Evolution, which has Maui, WinUI etc. as groups too. :)

P.S. As for tokens, I used it loosely for colors in "design tokens" sense, e.g. https://uxdesign.cc/design-tokens-for-dummies-8acebf010d71. Absolutely no problem explaining it simply. It's encouraging to see someone more experienced is broadly speaking on a similar trail of thought. So I'm not completely lost!

@FHWWC
Copy link

FHWWC commented Oct 26, 2022

Hello there!

I have a question about the code of MauiProgram.cs,.when I running the application,the log window will show a error msg say cannot find the functions 'events.AddWindows', but the tip window show many functions when I editing,this list show 'AddWindow' 'AddAndroid' etc..
And another line 'using MySolutionName.WinUI' has same problem, I can found items in tip window but the log window will show error msg say cannot found some function,some class. That's all of my question, my Windows.version is LTSC 2021 and SDKs installed full.
Can you help me please?

Thank you.

@LanceMcCarthy
Copy link
Author

@FHWWC Make sure you're using IF/ELIF compiler conditions.

Here' a real-world example you can compare against https://github.com/LanceMcCarthy/DevOpsExamples/blob/main/src/MAUI/MauiDemo/MauiProgram.cs

@FHWWC
Copy link

FHWWC commented Oct 27, 2022

Hello again!
Thanks for help, but the problem wasn't solved. The page background is white, or the application couldn't be running and still show error.

@FHWWC
Copy link

FHWWC commented Oct 27, 2022

SS

@LanceMcCarthy
Copy link
Author

@FHWWC
Copy link

FHWWC commented Oct 27, 2022

Yes I know, but the application background is white ,I have already followed your steps to change the code.
SS

@navi705
Copy link

navi705 commented Dec 28, 2022

Hello, can you help me? I have a problem with color or how I think with contrast. I use this code in winui 3 and maui, but the result is different. I using Windows 11. I tried to follow the link upper Lance's .NET MAUI Mica Demo, but link has expired. Sorry for my bad English. Thank you in advance

//WindowHelpers
using Microsoft.UI.Composition.SystemBackdrops;
using Microsoft.UI.Composition;
using Microsoft.UI.Xaml;
using Windows.UI.ViewManagement;
using WinRT;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI;

    public static class WindowHelpers
    {
        public static void TryMicaOrAcrylic(this Microsoft.UI.Xaml.Window window)
        {
            var dispatcherQueueHelper = new WindowsSystemDispatcherQueueHelper(); // in Platforms.Windows folder
            dispatcherQueueHelper.EnsureWindowsSystemDispatcherQueueController();

            // Hooking up the policy object
            var configurationSource = new SystemBackdropConfiguration();
            configurationSource.IsInputActive = true;

            switch (((FrameworkElement)window.Content).ActualTheme)
            {
                case ElementTheme.Dark:
                    configurationSource.Theme = SystemBackdropTheme.Dark;
                    break;
                case ElementTheme.Light:
                    configurationSource.Theme = SystemBackdropTheme.Light;
                    break;
                case ElementTheme.Default:
                    configurationSource.Theme = SystemBackdropTheme.Default;
                    break;
            }



            if (DesktopAcrylicController.IsSupported())
            {
                var acrylicController = new DesktopAcrylicController();
                acrylicController.LuminosityOpacity = 0.3f;
                acrylicController.TintOpacity = 0.7f;
                var uiSettings = new UISettings();
                var color = uiSettings.GetColorValue(UIColorType.AccentDark2);
                acrylicController.TintColor = color;
                acrylicController.FallbackColor = color;
                acrylicController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>());
                acrylicController.SetSystemBackdropConfiguration(configurationSource);



                window.Activated += (object sender, WindowActivatedEventArgs args) =>
                {
                    if (args.WindowActivationState is WindowActivationState.CodeActivated or WindowActivationState.PointerActivated)
                    {
                        // Handle situation where a window is activated and placed on top of other active windows.
                        if (acrylicController == null)
                        {
                            acrylicController = new DesktopAcrylicController();
                            acrylicController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>()); // Requires 'using WinRT;'
                            acrylicController.SetSystemBackdropConfiguration(configurationSource);
                        }
                    }

                    if (configurationSource != null)
                        configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated;
                };

                window.Closed += (object sender, WindowEventArgs args) =>
                {
                    if (acrylicController != null)
                    {
                        acrylicController.Dispose();
                        acrylicController = null;
                    }

                    configurationSource = null;
                };
            }

        }

    }



// WindowsSystemDispatcherQueueHelper
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Windows.System; 

    public class WindowsSystemDispatcherQueueHelper
    {
        [StructLayout(LayoutKind.Sequential)]
        struct DispatcherQueueOptions
        {
            internal int dwSize;
            internal int threadType;
            internal int apartmentType;
        }

        [DllImport("CoreMessaging.dll")]
        private static extern int CreateDispatcherQueueController([In] DispatcherQueueOptions options, [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object dispatcherQueueController);

        object m_dispatcherQueueController = null;

        public void EnsureWindowsSystemDispatcherQueueController()
        {
            if (DispatcherQueue.GetForCurrentThread() != null)
            {
                // one already exists, so we'll just use it.
                return;
            }

            if (m_dispatcherQueueController == null)
            {
                DispatcherQueueOptions options;

                options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
                options.threadType = 2;    // DQTYPE_THREAD_CURRENT
                options.apartmentType = 2; // DQTAT_COM_STA

                CreateDispatcherQueueController(options, ref m_dispatcherQueueController);
            }
        }
    }

image

@LanceMcCarthy
Copy link
Author

Hi @navi705 from the way that screenshot looks, the native window is applying the root frame transparency from Mica.

As to why the tint is a different color, I cannot say. There's also a difference int he titlebar color, too. I suspect that .NET MAUI is adding/changing something. I recommend opening a new issue in the MAUI repo https://github.com/dotnet/maui

Tip - When opening the issue, start with the screenshot, then put the code at the end. This will help communicate the message that something different is happening in MAUI than WinUI3.

@navi705
Copy link

navi705 commented Dec 29, 2022

Ok, thank you!

@veikkoeeva
Copy link

May be related to microsoft/WindowsAppSDK#3230.

As an aside, https://dotmorten.github.io/WinUIEx/, maybe have interesting helpersfor this code too (I don't know, if someone finds something, plase do share).

@LanceMcCarthy
Copy link
Author

Yep WinUIEx has some nice window position/size helpers. This gist example is specifically to add the window.TryMicaOrAcrylic() extension method to simplify the MAUI code.

For example, here I center and size the window => https://github.com/LanceMcCarthy/DevOpsExamples/blob/efbd26e7abe39738e518fb45d159a75bd84989ea/src/MAUI/MauiDemo/MauiProgram.cs#L44

I'm not sure if Morten has added the Acrylic/Mica stuff yet, but IIRC he mentioned to me it was in his plans.

Tip using WinUIEx, you can also use the persistence manager and remember the user's last window position and size:

#if WINDOWS10_0_17763_0_OR_GREATER
                
                events.AddWindows(wndLifeCycleBuilder =>
                {
                    wndLifeCycleBuilder.OnWindowCreated(window =>
                    {
                        // This remembers the user's last window position and size
                        var manager = WinUIEx.WindowManager.Get(window);
                        manager.PersistenceId = "MainWindowPersistanceId";
                        manager.MinWidth = 640;
                        manager.MinHeight = 480;

                        // Check for Mica or Acrylic support
                        window.TryMicaOrAcrylic();
                    });
                });

@kolkonos
Copy link

Lance,
Any chance you got this working with Shell Apps?
When using a single page, everything works fine. However, in a shell app, the following elements also get the Mica background resulting in a stacking of the effect:

  • Shell.TitleView
  • ShellContent

This results in the background for the page's content looking like it's not fully transparent.

If you have any insight as to how we could possible tap into the lifecycle of those components and set them to transparent, I would be very grateful.

You can see this especially well when you add the title bar to a flyout page.
image

@LanceMcCarthy
Copy link
Author

LanceMcCarthy commented Dec 19, 2023

Hi @kolkonos I'm sorry, I didn't see this until now.

What you want to do is not technically possible. That is because WinUI 2 and 3 does not support 100% transparent background Windows. You can get semi-transparent real-time blur (what is called Acrylic).

Update
I just realized you might be talking about the Shell page's background so that you can get the acrylic all the way through. I believe you can achieve that with Styles targeting ContentPage, Shell and possibly NavigationPage, then setting the BackgroundColor to Transparent. Though, I would ask the MAUI team for assistance with that if you're still stuck, you can get help here => https://learn.microsoft.com/en-us/answers/tags/247/dotnet-maui

@kolkonos
Copy link

Yeah, I wasn't talking about the shell, but as you pointed out, the background of the flyout header and content.
Setting those to have a background of transparent has no effect. Matter of fact, the screen shot I attached already has those properties set to transparent. I believe the internals of how those components are rendered (much like the label on a check box in Windows) is overriding the explicit background property. When inspecting the rendered UI, there are many pieces that are added by the platform, and which I cannot seem to be able to target with regular styling.

I will see if the MAUI team has any guidance for me.

@LanceMcCarthy
Copy link
Author

LanceMcCarthy commented Dec 29, 2023

NEW APPROACH

Hi folks, we no longer need a bunch of custom code. Microsoft now has an easy API to set the backdrop right on the Window class itself:

window.SystemBackdrop = new MicaBackdrop { Kind = MicaKind.BaseAlt };

Here's what it looks like in MauiProgram.cs

using Microsoft.Maui.LifecycleEvents;

#if WINDOWS10_0_17763_0_OR_GREATER
using Hacked.Maui.Platforms.Windows;
using Microsoft.UI.Composition.SystemBackdrops;
using Microsoft.UI.Xaml.Media;

#endif

namespace MyMauiApp;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

        builder.ConfigureLifecycleEvents(events =>
        {
#if WINDOWS10_0_17763_0_OR_GREATER
            events.AddWindows(wndLifeCycleBuilder =>
            {
                wndLifeCycleBuilder.OnWindowCreated(window =>
                {
                    window.SystemBackdrop = new MicaBackdrop { Kind = MicaKind.BaseAlt };
                });
            });
#endif
         }

        return builder.Build();
    }

Here is the result at runtime (note MicaKind.BaseAlt is more tinted than default Mica):

image

@FHWWC
Copy link

FHWWC commented Dec 29, 2023

That's good! I'm trying now...

@LanceMcCarthy
Copy link
Author

I haven't been able to test it in most situations, so I'd be happy to hear how it goes.

Here are the docs => https://learn.microsoft.com/en-us/windows/apps/design/style/mica#use-mica-with-the-windows-app-sdk

@FHWWC
Copy link

FHWWC commented Dec 30, 2023

It seems cannot put wasdk api on maui...

@LanceMcCarthy
Copy link
Author

LanceMcCarthy commented Dec 30, 2023 via email

@FHWWC
Copy link

FHWWC commented Dec 30, 2023

Oh sorry, I'm forgot to update the nuget package, now works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment