如何将Close命令绑定到按钮

时间:2009-06-30 20:32:19

标签: wpf button wpf-controls commandbinding

最简单的方法是实现ButtonClick事件处理程序并调用Window.Close()方法,但是如何通过Command绑定执行此操作?

7 个答案:

答案 0 :(得分:68)

所需要的只是一点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();
}

(改编自this MSDN article

答案 1 :(得分:57)

实际上,没有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设置为“window”,然后添加以下两个命名空间:

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 here

答案 2 :(得分:47)

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

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

中的RelayCommand
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}}}"/>

答案 3 :(得分:37)

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

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

不需要绑定,WPF会自动为您执行此操作!

参考:MSDN Button.IsCancel property

答案 4 :(得分:3)

对于.NET 4.5 SystemCommands类,可以解决问题(.NET 4.0用户可以使用WPF Shell扩展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}"/>

在Code Behind中你可以实现这样的处理程序:

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

    private void CloseWindow_Exec(object sender, ExecutedRoutedEventArgs e)
    {
        SystemCommands.CloseWindow(this);
    }

答案 5 :(得分:1)

一开始我在弄清楚它是如何工作的时候也遇到了一些麻烦所以我想对实际发生的情况做出更好的解释。

根据我的研究,处理这类事情的最佳方法是使用Command Bindings。会发生什么是&#34;消息&#34;广播到节目中的所有内容。所以你要做的就是使用CommandBinding。这基本上就是说&#34;当你听到这个消息时,这样做&#34;。

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

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;
}

现在我们需要设置&#34;连接&#34;在SystemCommands.CloseWindowCommandCloseApp以及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">

它实际上是一件非常简单的事情,只需设置Command和实际要执行的函数之间的链接,然后告诉Control将命令发送给你的程序的其余部分说&#34;好的每个人都运行你的函数用于Command CloseWindowCommand&#34;。

这实际上是处理这个问题的一种非常好的方法,因为你可以重复使用Executed Function而不需要像使用WinForms(使用ClickEvent并调用事件函数中的函数)那样的包装器,如:

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

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

我希望这能解决问题......

答案 6 :(得分: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来更改ViewModel的Close属性,该属性绑定到Behavior的Close属性。触发PropertyChanged事件时,“行为”将触发OnCloseTriggerChanged事件并关闭AssociatedObject ...(即窗口)。