【问题标题】:WPF Standard Commands - Where's Exit?WPF 标准命令 - 出口在哪里?
【发布时间】:2010-11-20 04:15:37
【问题描述】:

我正在我的 WPF 应用程序中创建一个标准菜单。

我知道我可以创建自定义命令,但我知道还有一堆标准命令可以绑定。

例如,要打开一个文件我应该绑定到 ApplicationCommands.Open,要关闭一个文件我应该绑定到 ApplicationCommands.Close。还有大量的 EditCommandsComponentCommandsNavigationCommands

似乎没有“退出”命令。我本来希望会有 ApplicationCommands.Exit.

我应该将什么绑定到“退出”菜单项?为这种通用的东西创建自定义命令似乎是错误的。

【问题讨论】:

    标签: wpf binding


    【解决方案1】:

    AFAIK 没有 ApplicationCommands.Quit 或 ApplicationCommands.Exit,所以我猜你必须自己创建它...

    无论如何,如果您使用的是MVVM pattern,RoutedCommands 并不是很方便,所以最好使用像RelayCommandDelegateCommand 这样的轻量级替代方案。

    【讨论】:

      【解决方案2】:

      您可以在将命令绑定到窗口之前修改它的 Text 属性。这将更改命令文本出现在您的用户界面中的所有位置。

      编辑:这样做可以在窗口或应用程序中关闭

      【讨论】:

        【解决方案3】:

        很遗憾,没有预定义的 ApplicationCommands.Exit。 2008 年 Microsoft Connect 上建议向 WPF 添加一个:http://connect.microsoft.com/VisualStudio/feedback/details/354300/add-predefined-wpf-command-applicationcommands-exit。但是,该项目已被标记为关闭/推迟。

        Mike Taulty 在他的博客文章中讨论了如何create your own Exit command

        【讨论】:

          【解决方案4】:

          实际上并没有那么复杂(但是,M$ 仍然因为不提供它而糟透了)。给你:

          public static class MyCommands
          {
              private static readonly ICommand appCloseCmd = new ApplicationCloseCommand();
              public static ICommand ApplicationCloseCommand
              {
                  get { return appCloseCmd; }
              }
          }
          
          //===================================================================================================
          public class ApplicationCloseCommand : ICommand
          {
              public event EventHandler CanExecuteChanged
              {
                  // You may not need a body here at all...
                  add { CommandManager.RequerySuggested += value; }
                  remove { CommandManager.RequerySuggested -= value; }
              }
          
              public bool CanExecute(object parameter)
              {
                  return Application.Current != null && Application.Current.MainWindow != null;
              }
          
              public void Execute(object parameter)
              {
                  Application.Current.MainWindow.Close();
              }
          }
          

          甚至可能不需要AplicationCloseCommand.CanExecuteChanged 事件处理程序的主体。

          你这样使用它:

          <MenuItem Header="{DynamicResource MenuFileExit}" Command="MyNamespace:MyCommands.ApplicationCloseCommand"/>
          

          干杯!

          (你无法想象我自己花了多长时间才发现这个命令的东西......)

          【讨论】:

            【解决方案5】:
            private void MenuItem_Click(object sender, RoutedEventArgs e)
                {
                    Application.Current.Shutdown();
                }
            

            【讨论】:

              【解决方案6】:

              做起来很简单:

              using System.Windows.Input;
              
              namespace YourApp
              {
                  static class ApplicationCommands
                  {    
                      public static RoutedCommand Quit { get; }    
              
                      static ApplicationCommands()
                      {
                          var inputGestures = new InputGestureCollection();
                          inputGestures.Add(new KeyGesture(Key.Q, ModifierKeys.Control));
                          Quit = new RoutedUICommand("Quit", "Quit", typeof(ApplicationCommands),
                              inputGestures);
                      }
                  }
              }
              

              像这样在你的 XAML 中使用它:

              <Window.CommandBindings>
                  <CommandBinding Command="local:ApplicationCommands.Quit" 
                                  Executed="QuitCommandOnExecuted"/>
              </Window.CommandBindings>
              
              [..]
              
              <MenuItem Command="local:ApplicationCommands.Quit" />
              

              代码隐藏:

              void QuitCommandOnExecuted(object sender, ExecutedRoutedEventArgs e)
              {
                  Application.Current.Shutdown();
              }
              

              【讨论】:

                【解决方案7】:

                是的,Microsoft 将ApplicationCommands.Exit 命令包含在他们的预定义命令集合中会很有意义。令我失望的是他们没有。但正如这个问题的答案所表明的那样,并非一切都丢失了。

                对于缺少正确的ApplicationCommands.Exit 对象,有很多解决方法。但是,我觉得最没抓住重点。他们要么在视图模型中实现某些东西,对于严格来说是视图行为的东西(在某些情况下使用例如Application.Current.MainWindow! 进入视图对象图),要么他们编写一堆代码隐藏来执行 XAML 所做的事情非常好,更方便。

                恕我直言,最简单的方法就是为窗口声明一个RoutedUICommand 资源,将其附加到命令绑定和菜单项,以连接所有部分。例如:

                <Window x:Class="ConwaysGameOfLife.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                        mc:Ignorable="d"
                        Title="MainWindow" Height="450" Width="800">
                
                  <Window.Resources>
                    <RoutedUICommand x:Key="fileExitCommand" Text="File E_xit">
                      <RoutedUICommand.InputGestures>
                        <KeyGesture >Alt+F4</KeyGesture>
                      </RoutedUICommand.InputGestures>
                    </RoutedUICommand>
                  </Window.Resources>
                
                  <Window.CommandBindings>
                    <CommandBinding Command="{StaticResource fileExitCommand}" Executed="fileExitCommand_Executed"/>
                  </Window.CommandBindings>
                
                  <DockPanel>
                    <Menu DockPanel.Dock="Top">
                      <MenuItem Header="_File">
                        <!-- other menu items go here -->
                        <Separator/>
                        <MenuItem Command="{StaticResource fileExitCommand}"/>
                      </MenuItem>
                    </Menu>
                    <!-- the main client area UI goes here -->
                  </DockPanel>
                
                </Window>
                

                命令绑定的Executed 事件处理程序很简单:

                private void fileExitCommand_Executed(object sender, ExecutedRoutedEventArgs e)
                {
                    Close();
                }
                

                当然,假设您的程序实现遵循关闭主窗口以退出程序的通常语义。

                通过这种方式,所有特定于 UI 的元素都直接进入 RoutedUICommand 对象,可以在 XAML 中正确方便地进行配置,而不必声明一个新的 C# 类来实现命令和/或弄乱代码隐藏的输入绑定。 MenuItem 对象已经知道如何处理 RoutedUICommand 在显示方面,因此走这条路线可以很好地将命令的属性与 UI 的其余部分解耦。它还提供了一种方便的方式来提供辅助键手势,以防您更喜欢默认的 Alt+F4 以外的其他东西(例如 Ctrl+W)。

                您甚至可以将RoutedUICommand 声明放在 App.xaml 文件中,以便在程序中的多个窗口之间重复使用(如果它们存在)。同样,将资源中声明的 UI 特定方面与整个程序中的消费者解耦。

                我发现这种方法比我见过的其他选项(这里和其他地方)更通用和更容易实现。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-05-22
                  • 2019-11-03
                  相关资源
                  最近更新 更多