I'm building a WinUI 3 desktop application with a custom TitleBar
. I've applied FlowDirection="RightToLeft"
to the main grid in my MainWindow.xaml
, but the caption buttons (minimize, maximize, close) and the title alignment remain in left-to-right layout.
<Window
x:Class="YourNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:YourNamespace">
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<Grid x:Name="MainGrid" RowDefinitions="auto,*">
<TitleBar
Title="Custom Title Bar"
IsBackButtonEnabled="True"
IsBackButtonVisible="True"
Subtitle="Beta">
<TitleBar.RightHeader>
<PersonPicture Height="25" Initials="JD" />
</TitleBar.RightHeader>
</TitleBar>
<StackPanel Grid.Row="1">
<Button Content="Click" />
</StackPanel>
</Grid>
</Window>
Code behind file:
public sealed partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MainGrid.FlowDirection = FlowDirection.RightToLeft;
ExtendsContentIntoTitleBar = true;
this.AppWindow.TitleBar.IconShowOptions = Microsoft.UI.Windowing.IconShowOptions.ShowIconAndSystemMenu;
this.AppWindow.TitleBar.ButtonBackgroundColor = Microsoft.UI.Colors.Transparent;
this.AppWindow.TitleBar.PreferredHeightOption = Microsoft.UI.Windowing.TitleBarHeightOption.Tall;
}
}
What I expect:
The custom TitleBar content and caption buttons should appear mirrored, with caption buttons on the left side when FlowDirection.RightToLeft is applied.
What happens instead: Only the internal elements (MainGrid) respect RightToLeft.
The caption buttons and title remain in LeftToRight layout.
Question: How can I force the caption buttons and title bar in a WinUI 3 custom title bar to follow FlowDirection.RightToLeft? Is this a known limitation or am I missing a specific setting?
Thanks!
I tried the following code from the GitHub repo, and it seems to be working:
<Window
x:Class="WinUIApp3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:WinUIApp3"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="TitleBarPageWindowGrid" RowDefinitions="Auto,*">
<TitleBar x:Name="AppTitleBar"
Title="TITLE"
Grid.Row="0"
Subtitle="SUBTITLE" />
</Grid>
</Window>
public sealed partial class MainWindow : Window
{
const int GWL_EXSTYLE = -20;
const int WS_EX_LAYOUTRTL = 0x00400000;
public MainWindow()
{
InitializeComponent();
ExtendsContentIntoTitleBar = true;
SetTitleBar(AppTitleBar);
TitleBarPageWindowGrid.FlowDirection = FlowDirection.RightToLeft;
UpdateCaptionButtonDirection(FlowDirection.RightToLeft);
}
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
internal static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, nint newProc);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
internal static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
private static nint GetWindowHandleForCurrentWindow(object target) =>
WinRT.Interop.WindowNative.GetWindowHandle(target);
private void UpdateCaptionButtonDirection(FlowDirection direction)
{
var hwnd = GetWindowHandleForCurrentWindow(this);
if (hwnd != 0)
{
var exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
if (direction == FlowDirection.RightToLeft)
{
exStyle |= WS_EX_LAYOUTRTL;
}
else
{
exStyle &= ~WS_EX_LAYOUTRTL;
}
SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle);
}
}
}