最简单的方法是实现ButtonClick
事件处理程序和调用Window.Close()
方法,但是如何通过Command
绑定来实现呢?
7 回答
所需要的只是一点 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 文章)
实际上,没有 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 。
我认为在现实世界的场景中,一个简单的点击处理程序可能比过于复杂的基于命令的系统更好,但你可以这样做:
使用本文中的 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}}}"/>
如果窗口显示为Window.ShowDialog()
:
我知道的最简单的解决方案是将IsCancel
属性设置为 true 的 close Button
:
<Button Content="Close" IsCancel="True" />
无需绑定,WPF 会自动为您完成!
此属性提供了一种简单的方式来表示这些是对话框上的“确定”和“取消”按钮。它还将键绑定ESC到按钮。
对于.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);
}
一开始我也很难弄清楚它是如何工作的,所以我想对实际发生的事情进行更好的解释。
根据我的研究,处理此类事情的最佳方法是使用命令绑定。所发生的是向程序中的所有内容广播“消息”。所以你要做的就是使用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.CloseWindowCommand
and 和CloseApp
and之间设置“连接”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 执行附加到命令的函数。
我希望这可以解决问题...
我发现可行的一个选项是将此功能设置为行为。
行为:
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...,即窗口。