如何使用.NET MAUI自定义Windows 10标题栏并添加交互组件
我之前找到过一个通过WinUI修改Windows 10/11标题栏的方案,但在.NET MAUI里没法直接套用其中针对Windows 10的方法——WinUI的SetTitleBar(AppTitleBar);方法需要传入Microsoft.UI.Xaml.UIElement类型的对象,而MAUI使用独立的视觉组件体系,官方文档也未提及MAUI相关的标题栏自定义方案。以下是实现Windows 10标题栏完全自定义(含交互组件)的可行步骤:
实现步骤
1. 接入WinUI底层窗口实例
MAUI的Windows平台本质基于WinUI框架,我们可以在项目的Platforms/Windows目录下的代码中,获取到WinUI的窗口实例。比如在App.xaml.cs或者页面的平台特定代码里,通过MauiWinUIWindow拿到对应的AppWindow对象。
2. 创建WinUI自定义标题栏控件
在Platforms/Windows目录下新建WinUI用户控件(比如命名为CustomTitleBar.xaml),在这个控件里添加你需要的交互组件(按钮、搜索框等),并设置好样式、布局和背景色,完全按照WinUI的方式开发即可。
3. 关联自定义标题栏与MAUI窗口
在Windows平台的初始化代码中,将自定义标题栏绑定到窗口,并调整MAUI页面的边距,避免内容被标题栏遮挡:
// 示例:在Platforms/Windows/App.xaml.cs的OnLaunched方法中 protected override void OnLaunched(LaunchActivatedEventArgs args) { base.OnLaunched(args); var mauiWindow = Application.Current.Windows.FirstOrDefault()?.Handler?.PlatformView as MauiWinUIWindow; if (mauiWindow == null) return; var appWindow = mauiWindow.AppWindow; // 实例化自定义标题栏 var customTitleBar = new CustomTitleBar(); // 设置为窗口标题栏 appWindow.TitleBar.SetTitleBar(customTitleBar); // 调整MAUI主页面边距,避免内容被标题栏覆盖 if (Application.Current.MainPage != null) { Application.Current.MainPage.Padding = new Thickness(0, appWindow.TitleBar.Height, 0, 0); } }
4. 实现交互组件逻辑
在自定义标题栏的后台代码中,给交互组件绑定事件处理逻辑,比如窗口最小化、最大化、关闭按钮的点击事件:
<!-- CustomTitleBar.xaml 示例代码 --> <UserControl x:Class="YourAppName.Platforms.Windows.CustomTitleBar" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="32"> <Grid Background="#2C3E50"> <!-- 左侧可拖动区域 --> <Grid x:Name="DragArea" HorizontalAlignment="Left" Width="200" Background="Transparent"/> <!-- 右侧交互按钮 --> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,10,0"> <Button x:Name="MinimizeBtn" Content="—" Width="40" Height="32" Background="Transparent" Foreground="White"/> <Button x:Name="MaximizeBtn" Content="□" Width="40" Height="32" Background="Transparent" Foreground="White"/> <Button x:Name="CloseBtn" Content="×" Width="40" Height="32" Background="Transparent" Foreground="White"/> </StackPanel> </Grid> </UserControl>
// CustomTitleBar.xaml.cs 后台逻辑 public sealed partial class CustomTitleBar : UserControl { public CustomTitleBar() { this.InitializeComponent(); // 绑定拖动窗口逻辑 DragArea.PointerPressed += (s, e) => Window.GetWindow(this).DragMove(); // 绑定按钮事件 MinimizeBtn.Click += MinimizeBtn_Click; MaximizeBtn.Click += MaximizeBtn_Click; CloseBtn.Click += CloseBtn_Click; } private void MinimizeBtn_Click(object sender, RoutedEventArgs e) { Window.GetWindow(this).WindowState = WindowState.Minimized; } private void MaximizeBtn_Click(object sender, RoutedEventArgs e) { var window = Window.GetWindow(this); window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; } private void CloseBtn_Click(object sender, RoutedEventArgs e) { Window.GetWindow(this).Close(); } }
5. 适配Windows 10标题栏行为
Windows 10下需要确保标题栏的拖动、窗口状态切换等原生行为正常工作,上面的代码中已经通过DragArea的PointerPressed事件实现了窗口拖动,同时按钮事件也处理了窗口的状态控制,完全覆盖原生标题栏的功能。
内容的提问来源于stack exchange,提问作者stack-delay

