最も簡単な方法はButtonClick
イベントハンドラを実装してWindow.Close()
メソッドを呼び出すことですが、Command
バインディングを使用してこれを行う方法は?
現実のシナリオでは、単純なクリックハンドラは、複雑すぎるコマンドベースのシステムよりも優れていると思いますが、次のようなことができます。
この記事の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}}}"/>
必要なのは、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#コードがなくてもis可能です。インタラクションを使用することが重要です:
<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
をウィンドウの「ウィンドウ」に追加し、次の2つの名前空間を追加します。
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 。
私が知っている最も簡単な解決策は、IsCancel
プロパティをclose Button
のtrueに設定することです:
<Button Content="Close" IsCancel="True" />
バインディングは不要です。WPFが自動的に行います!
。NET 4.5 SystemCommands クラスの場合、トリックが行われます(.NET 4.0ユーザーはWPF Shell Extension google-Microsoft.Windows.ShellまたはNicholas Solutionを使用できます)。
<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
がブロードキャストされたときに呼び出される関数を設定することです。オプションで、コマンドを実行するかどうかを決定する関数を割り当てることができます。たとえば、フォームを閉じて、ユーザーが保存したかどうかを確認します。
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
とCloseApp
およびCloseAppCanExecute
の間の「接続」を設定する必要があります
<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">
それは実際には非常に簡単なことです。コマンドと実行する実際の関数とのリンクを設定して、コントロールにコマンドをプログラムの残りの部分に送信するように伝えます。
これは実際にこれを処理する非常に素晴らしい方法です。なぜなら、次のようなWinForms(ClickEventを使用し、イベント関数内で関数を呼び出す)のようにラッパーを持たずに、実行済み関数を再利用できるからです。
protected override void OnClick(EventArgs e){
/*** Function to Execute ***/
}
WPFでは、関数をコマンドにアタッチし、代わりにコマンドにアタッチされた関数を実行するようUIElementに指示します。
これで問題が解決することを願っています...
動作することがわかった1つのオプションは、この関数を動作として設定することです。
動作:
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ウィンドウで、それへの参照を設定し、ビヘイビアーのCloseプロパティをViewModelのブール「Close」プロパティにバインドします。
xmlns:i="http://schemas.Microsoft.com/expression/2010/interactivity"
<i:Interaction.Behaviors>
<behavior:WindowCloseBehavior Close="{Binding Close}" />
</i:Interaction.Behaviors>
そのため、ビューからICommandを割り当てて、ビヘイビアーのCloseプロパティにバインドされているViewModelのCloseプロパティを変更します。 PropertyChangedイベントが発生すると、ビヘイビアーはOnCloseTriggerChangedイベントを発生させ、WindowであるAssociatedObject ...を閉じます。