66

最简单的方法是实现ButtonClick事件处理程序和调用Window.Close()方法,但是如何通过Command绑定来实现呢?

4

7 回答 7

81

所需要的只是一点 XAML ......

<Window x:Class="WCSamples.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Close"
                        Executed="CloseCommandHandler"/>
    </Window.CommandBindings>
    <StackPanel Name="MainStackPanel">
        <Button Command="ApplicationCommands.Close" 
                Content="Close Window" />
    </StackPanel>
</Window>

还有一点 C#...

private void CloseCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
    this.Close();
}

(改编自这篇 MSDN 文章

于 2009-06-30T21:02:49.627 回答
69

实际上,没有 C# 代码也是可能的。关键是使用交互:

<Button Content="Close">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <ei:CallMethodAction TargetObject="{Binding ElementName=window}" MethodName="Close"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

为了使它工作,只需将x:Name窗口的设置为“窗口”,并添加这两个命名空间:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

这要求您将 Expression Blend SDK DLL 添加到您的项目中,特别是Microsoft.Expression.Interactions.

如果您没有 Blend,可以在此处下载 SDK 。

于 2011-04-12T11:51:10.760 回答
55

我认为在现实世界的场景中,一个简单的点击处理程序可能比过于复杂的基于命令的系统更好,但你可以这样做:

使用本文中的 RelayCommand http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

public class MyCommands
{
    public static readonly ICommand CloseCommand =
        new RelayCommand( o => ((Window)o).Close() );
}
<Button Content="Close Window"
        Command="{X:Static local:MyCommands.CloseCommand}"
        CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, 
                           AncestorType={x:Type Window}}}"/>
于 2009-07-01T14:18:32.240 回答
50

如果窗口显示为Window.ShowDialog()

我知道的最简单的解决方案是将IsCancel属性设置为 true 的 close Button

<Button Content="Close" IsCancel="True" />

无需绑定,WPF 会自动为您完成!

此属性提供了一种简单的方式来表示这些是对话框上的“确定”和“取消”按钮。它还将键绑定ESC到按钮。

参考:MSDN Button.IsCancel 属性

于 2014-10-31T16:25:34.567 回答
5

对于.NET 4.5 SystemCommands类可以解决问题(.NET 4.0 用户可以使用 WPF Shell Extension google - Microsoft.Windows.Shell 或 Nicholas 解决方案)。

    <Window.CommandBindings>
        <CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" 
                        CanExecute="CloseWindow_CanExec" 
                        Executed="CloseWindow_Exec" />
    </Window.CommandBindings>
    <!-- Binding Close Command to the button control -->
    <Button ToolTip="Close Window" Content="Close" Command="{x:Static SystemCommands.CloseWindowCommand}"/>

在后面的代码中,您可以像这样实现处理程序:

    private void CloseWindow_CanExec(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    private void CloseWindow_Exec(object sender, ExecutedRoutedEventArgs e)
    {
        SystemCommands.CloseWindow(this);
    }
于 2015-04-15T16:53:39.590 回答
3

一开始我也很难弄清楚它是如何工作的,所以我想对实际发生的事情进行更好的解释。

根据我的研究,处理此类事情的最佳方法是使用命令绑定。所发生的是向程序中的所有内容广播“消息”。所以你要做的就是使用CommandBinding. 这实质上是说“当你听到这个消息时做这个”。

所以在用户试图关闭窗口的问题中。SystemCommand.CloseWindowCommand我们需要做的第一件事是设置广播时将调用的函数。或者,您可以分配一个函数来确定是否应该执行命令。一个示例是关闭表单并检查用户是否已保存。

MainWindow.xaml.cs(或其他代码隐藏)

void CloseApp( object target, ExecutedRoutedEventArgs e ) {
    /*** Code to check for State before Closing ***/
    this.Close();
}

void CloseAppCanExecute( object sender, CanExecuteRoutedEventArgs e ) {
    /*** Logic to Determine if it is safe to Close the Window ***/
    e.CanExecute = true;
}

现在我们需要在SystemCommands.CloseWindowCommandand 和CloseAppand之间设置“连接”CloseAppCanExecute

MainWindow.xaml(或任何实现 CommandBindings 的东西)

<Window.CommandBindings>
    <CommandBinding Command="SystemCommands.CloseWindowCommand"
                    Executed="CloseApp"
                    CanExecute="CloseAppCanExecute"/>
</Window.CommandBindings>

如果您知道命令应该始终可以执行,则可以省略 CanExecute 保存可能是一个很好的示例,具体取决于应用程序。这是一个例子:

<Window.CommandBindings>
    <CommandBinding Command="SystemCommands.CloseWindowCommand"
                    Executed="CloseApp"/>
</Window.CommandBindings>

最后,您需要告诉 UIElement 发出 CloseWindowCommand。

<Button Command="SystemCommands.CloseWindowCommand">

它实际上是一件非常简单的事情,只需设置命令和实际要执行的函数之间的链接,然后告诉控件将命令发送到程序的其余部分,说“好的,每个人都为命令 CloseWindowCommand 运行你的函数”。

这实际上是一种非常好的处理方式,因为您可以重用执行函数,而无需像 WinForms 那样使用包装器(使用 ClickEvent 并在事件函数中调用函数),例如:

protected override void OnClick(EventArgs e){
    /*** Function to Execute ***/
}

在 WPF 中,您将函数附加到命令并告诉 UIElement 执行附加到命令的函数。

我希望这可以解决问题...

于 2017-02-23T14:12:03.267 回答
0

我发现可行的一个选项是将此功能设置为行为。

行为:

    public class WindowCloseBehavior : Behavior<Window>
{
    public bool Close
    {
        get { return (bool) GetValue(CloseTriggerProperty); }
        set { SetValue(CloseTriggerProperty, value); }
    }

    public static readonly DependencyProperty CloseTriggerProperty =
        DependencyProperty.Register("Close", typeof(bool), typeof(WindowCloseBehavior),
            new PropertyMetadata(false, OnCloseTriggerChanged));

    private static void OnCloseTriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behavior = d as WindowCloseBehavior;

        if (behavior != null)
        {
            behavior.OnCloseTriggerChanged();
        }
    }

    private void OnCloseTriggerChanged()
    {
        // when closetrigger is true, close the window
        if (this.Close)
        {
            this.AssociatedObject.Close();
        }
    }
}

在 XAML 窗口中,设置对它的引用并将 Behavior 的 Close 属性绑定到 ViewModel 上的布尔“Close”属性:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<i:Interaction.Behaviors>
    <behavior:WindowCloseBehavior Close="{Binding Close}" />
</i:Interaction.Behaviors>

因此,从 View 分配一个 ICommand 以更改绑定到 Behavior 的 Close 属性的 ViewModel 上的 Close 属性。当 PropertyChanged 事件被触发时,行为触发 OnCloseTriggerChanged 事件并关闭 AssociatedObject...,即窗口。

于 2018-07-18T18:25:37.927 回答