【问题标题】:Why is the WPF ApplicationCommands.Close command disabled on the button and in the menu item?为什么在按钮和菜单项中禁用 WPF ApplicationCommands.Close 命令?
【发布时间】:2020-08-30 01:37:51
【问题描述】:

问题

为什么在按钮和菜单项中禁用 WPF ApplicationCommands.Close 命令?

代码

<Window x:Class="ApplicationCloseCommand.Views.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"
        xmlns:viewModels="clr-namespace:ApplicationCloseCommand.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="169.493" Width="319.273">
    <Window.DataContext>
        <viewModels:MainWindowViewModel />
    </Window.DataContext>
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem Header="_Exit" Command="Close"/>
            </MenuItem>
        </Menu>
        <Canvas>
            <Button Content="Close" Command="Close" Height="23" VerticalAlignment="Top" Canvas.Left="142" Canvas.Top="31"/>
        </Canvas>
    </DockPanel>
</Window>

研究

Some sources 说要自己实现 ICommand 并在命令处理程序中执行 this.Close()。但是,我不明白为什么ApplicationCommands.Close 存在。

Some sources 表示需要实现CanExecute 方法以返回true。但同样,如果我必须自己做这件事,包括CloseCommandHandler(来自链接的示例),ApplicationCommands.Close 有什么好处?

Some sources 提及CommandTarget。这不起作用:

<MenuItem Header="_Exit" Command="Close" CommandTarget="{Binding ElementName=MyMainWindow}"/>

我是不是在 CommandTarget 上做错了?

【问题讨论】:

    标签: wpf xaml icommand


    【解决方案1】:

    ApplicationCommands,如 NavigationCommandsComponentCommands 公开一组预定义的常用 UI 命令。它们都是RoutedCommand 的实现。 RoutedCommandRoutedUICommand实现 ICommand

    RoutedCommand 没有实现 ExecuteCanExecute 方法。它只是引发了相应的RoutedEvent

    此事件将遍历可视化树,直到由 CommandBinding 处理。定义或执行CanExecuteExecute 方法或特殊事件处理程序的是CommandBinding。这意味着可以在引发RoutedCommand 的树上的某处定义实际的命令实现。

    有一些控件实现了默认的CommandBinding(或命令实现)。 TextBox 可以处理例如ApplicationCommands.CopyRoutedCommand。或者DocumentViewer 可以处理 NavigationCommands.NextPage RoutedCommand。 ApplicationCommands.Close 没有任何控件提供的支持者或默认实现。

    RoutedCommand 旨在用于 UI 上下文,例如执行控件的行为。这种逻辑永远不应该在视图模型中处理。因此,ApplicationCommands.Close 必须由一个控件或附加到可视化树的行为来实现。
    对于数据相关的行为或逻辑,您必须提供自己的 ICommand 实现,该实现具有在视图模型中定义的处理程序。

    如果您将 RoutedCommand 例如 ApplicationCommands.Close 分配给命令源,例如Button,但不为此 RoutedCommand 提供处理程序,因此命令源不存在 CanExecute 处理程序,例如Button 假定 CanExecute 为 false 并禁用自身。

    这意味着您必须提供CommandBinding

    MainWindow.xaml

    <Window>
      <Window.CommandBindings>
        <CommandBinding Command="{x:Static ApplicationCommands.Close}"
                        Executed="ExecutedCloseCommand"
                        CanExecute="CanExecuteCloseCommand" />
      </Window.CommandBindings>
    
      <Button Command="{x:Static ApplicationCommands.Close}"
              Content="Close Window"/>
    </Window>
    

    MainWindow.xaml.cs

    private void CanExecuteCloseCommand(object sender,
        CanExecuteRoutedEventArgs e)
    {
       e.CanExecute = true;
    }
    
    private void ExecutedCloseCommand(object sender,
        ExecutedRoutedEventArgs e)
    {
      this.Close();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-08
      • 1970-01-01
      • 2014-10-09
      • 2011-09-13
      • 2012-11-25
      • 2011-04-24
      • 1970-01-01
      • 2010-11-17
      相关资源
      最近更新 更多