在UWP中如何通过自定义按钮触发标题栏的最小化/最大化/关闭操作?
UWP自定义按钮模拟标题栏最小化、最大化、关闭操作的实现方案
当然可以实现该功能。UWP没有WPF的SystemCommands类,但可以通过ApplicationView(窗口状态控制)和CoreApplication(窗口/应用关闭)的原生API直接实现对应操作,以下是分场景的详细实现步骤:
核心依赖命名空间
首先确保代码文件中引用以下命名空间:
using Windows.ApplicationModel.Core; using Windows.UI.ViewManagement; using Windows.UI.Xaml.Navigation;
一、基础实现(代码后台绑定点击事件)
1. 最小化窗口
XAML按钮定义:
<Button Content="最小化" Click="MinimizeButton_Click" Margin="4" />
后台点击事件处理:
private async void MinimizeButton_Click(object sender, RoutedEventArgs e) { // 仅在桌面环境下执行(移动端无窗口概念) if (ApplicationView.GetForCurrentView().WindowingEnvironment == WindowingEnvironment.Desktop) { // TryMinimizeAsync支持Windows 10 1607及以上版本,兼容性覆盖绝大多数设备 await ApplicationView.GetForCurrentView().TryMinimizeAsync(); } }
2. 最大化/还原窗口(支持状态切换)
XAML按钮定义(命名用于状态同步):
<Button x:Name="MaxRestoreBtn" Content="最大化" Click="MaxRestoreBtn_Click" Margin="4" />
后台点击事件处理:
private async void MaxRestoreBtn_Click(object sender, RoutedEventArgs e) { var currentView = ApplicationView.GetForCurrentView(); if (currentView.WindowingEnvironment != WindowingEnvironment.Desktop) return; // 先退出全屏模式(如果当前是全屏) if (currentView.IsFullScreenMode) { await currentView.ExitFullScreenModeAsync(); } // 根据当前状态切换最大化/还原 if (currentView.IsMaximized) { await currentView.TryRestoreAsync(); MaxRestoreBtn.Content = "最大化"; } else { await currentView.TryMaximizeAsync(); MaxRestoreBtn.Content = "还原"; } }
状态同步优化:当用户通过系统标题栏改变窗口状态时,同步自定义按钮的显示文本,在页面导航事件中注册监听:
protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); ApplicationView.GetForCurrentView().VisibleBoundsChanged += CurrentView_VisibleBoundsChanged; UpdateMaxRestoreBtnText(); } protected override void OnNavigatedFrom(NavigationEventArgs e) { base.OnNavigatedFrom(e); ApplicationView.GetForCurrentView().VisibleBoundsChanged -= CurrentView_VisibleBoundsChanged; } private void CurrentView_VisibleBoundsChanged(ApplicationView sender, object args) { UpdateMaxRestoreBtnText(); } private void UpdateMaxRestoreBtnText() { MaxRestoreBtn.Content = ApplicationView.GetForCurrentView().IsMaximized ? "还原" : "最大化"; }
3. 关闭窗口/应用
XAML按钮定义:
<Button Content="关闭" Click="CloseButton_Click" Margin="4" />
后台点击事件处理(两种场景可选):
private void CloseButton_Click(object sender, RoutedEventArgs e) { // 场景1:仅关闭当前窗口(多窗口应用适用) CoreApplication.GetCurrentView().CoreWindow.Close(); // 场景2:直接退出整个应用(单窗口应用常用) // Application.Current.Exit(); }
二、MVVM模式实现(命令绑定)
如果采用MVVM架构,可通过自定义RelayCommand实现命令绑定,避免代码后台的事件耦合:
1. 实现基础RelayCommand类
public class RelayCommand : ICommand { private readonly Action _execute; private readonly Func<bool> _canExecute; public RelayCommand(Action execute, Func<bool> canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true; public void Execute(object parameter) => _execute(); public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); }
2. ViewModel定义命令与状态属性
public class MainViewModel : INotifyPropertyChanged { public ICommand MinimizeCommand { get; } public ICommand MaxRestoreCommand { get; } public ICommand CloseCommand { get; } private bool _isMaximized; public bool IsMaximized { get => _isMaximized; set { _isMaximized = value; OnPropertyChanged(); } } public MainViewModel() { // 最小化命令 MinimizeCommand = new RelayCommand(async () => { if (ApplicationView.GetForCurrentView().WindowingEnvironment == WindowingEnvironment.Desktop) { await ApplicationView.GetForCurrentView().TryMinimizeAsync(); } }); // 最大化/还原命令 MaxRestoreCommand = new RelayCommand(async () => { var currentView = ApplicationView.GetForCurrentView(); if (currentView.WindowingEnvironment != WindowingEnvironment.Desktop) return; if (currentView.IsFullScreenMode) await currentView.ExitFullScreenModeAsync(); if (currentView.IsMaximized) await currentView.TryRestoreAsync(); else await currentView.TryMaximizeAsync(); // 更新状态属性 IsMaximized = currentView.IsMaximized; }); // 关闭命令 CloseCommand = new RelayCommand(() => CoreApplication.GetCurrentView().CoreWindow.Close()); // 监听窗口状态变化,同步IsMaximized属性 ApplicationView.GetForCurrentView().VisibleBoundsChanged += (s, e) => { IsMaximized = ApplicationView.GetForCurrentView().IsMaximized; }; } // 实现INotifyPropertyChanged接口 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
3. XAML绑定与转换器
首先实现布尔值转文本的转换器:
public class BoolToMaxRestoreTextConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { return (bool)value ? "还原" : "最大化"; } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } }
在页面资源中声明转换器并绑定ViewModel:
<Page.Resources> <local:BoolToMaxRestoreTextConverter x:Key="BoolToMaxRestoreTextConverter" /> </Page.Resources> <Page.DataContext> <local:MainViewModel /> </Page.DataContext> <!-- 按钮绑定 --> <Button Content="最小化" Command="{Binding MinimizeCommand}" Margin="4" /> <Button Content="{Binding IsMaximized, Converter={StaticResource BoolToMaxRestoreTextConverter}}" Command="{Binding MaxRestoreCommand}" Margin="4" /> <Button Content="关闭" Command="{Binding CloseCommand}" Margin="4" />
三、关键注意事项
- 设备兼容性:所有窗口控制API仅在桌面版Windows 10/11上有效,移动端UWP无窗口概念,调用前建议通过
WindowingEnvironment.Desktop判断环境。 - 异步处理:
TryMinimizeAsync、TryMaximizeAsync等方法为异步操作,需用await调用避免UI线程阻塞。 - 多窗口场景:
ApplicationView.GetForCurrentView()获取的是当前激活窗口的视图,确保操作目标正确。
内容的提问来源于stack exchange,提问作者ricky rocky
相关产品推荐
相关产品推荐

