はじめに
仕事でOKボタンを押したらシャットダウンする自作windowを作る機会があったのですが、
「windowが表示されたときにEnterキー押したら、OKボタンのクリックイベントが実行されるようにしてね」と言われました。
言われるまではクリックでok等のボタンイベントが正常か確認していましたが、キーイベントでの挙動は見ていなかったのでこの機会に少しまとめてみました。
IsDefaultとIsCancelという便利なプロパティがwpfのボタンには存在するようなので、それを使ってみます。
作ったサンプル
テキストボックスを1つと、ボタンを5つ並べました。
default(okCancel)と書かれたボタンにIsDefault=Trueを割り当て、escape(ync)と書かれたボタンにIsCancel=Trueを割り当てています。
各ボタンにはクリックイベントを割り当てていて、show NodDefWin以外はメッセージボックスを表示させています。
xaml
<GridBackground="#b33e5c"><Grid.ColumnDefinitions><ColumnDefinitionWidth="*"></ColumnDefinition><ColumnDefinitionWidth="*"></ColumnDefinition><ColumnDefinitionWidth="*"></ColumnDefinition></Grid.ColumnDefinitions><GridGrid.ColumnSpan="3"><TextBlockx:Name="text"Text="result"/></Grid><!--Defaultのボタン--><GridGrid.Column="0"><ButtonContent="default(okCancel)"Width="100"Height="30"Click="Button_Default"IsDefault="True"/></Grid><GridGrid.Column="1"><StackPanel><!--Escape時に選択されるボタン--><ButtonContent="escape(ync)"Width="100"Height="30"IsCancel="True"Click="Button_Escape"/><ButtonContent="onlyOk"Width="100"Height="30"Click="Button_OnlyOK"/><ButtonContent="YsNo"Width="100"Height="30"Click="Button_YesNo"/></StackPanel></Grid><GridGrid.Column="2"><ButtonContent="show NoDefWin"Width="100"Height="30"Click="Button_Custom"/></Grid></Grid>
xaml.cs
privatevoidButton_Default(objectsender,RoutedEventArgse){varr=MessageBox.Show("Enter default ok","caption",MessageBoxButton.OKCancel);this.text.Text=r.ToString();}privatevoidButton_Escape(objectsender,RoutedEventArgse){varr=MessageBox.Show("Enter","caption",MessageBoxButton.YesNoCancel);this.text.Text=r.ToString();}privatevoidButton_OnlyOK(objectsender,RoutedEventArgse){varr=MessageBox.Show("Enter","caption",MessageBoxButton.OK);this.text.Text=r.ToString();}privatevoidButton_YesNo(objectsender,RoutedEventArgse){varr=MessageBox.Show("Enter","caption",MessageBoxButton.YesNo);this.text.Text=r.ToString();}/// 自作のwindowクラスを表示するprivatevoidButton_Custom(objectsender,RoutedEventArgse){vars=newSubWindow();s.ShowDialog();}
動作
Enterキー
default(okCancel) と書かれたボタンの IsDefault=Trueにしているので、アプリ起動時にEnterを押すとこのボタンのClickイベントが実行されて、MessageBoxButton.OKCancelのメッセージボックスが表示されます。
MessageBoxButton.OKCancelのメッセージボックスは OKボタンがIsDefault=Trueで キャンセルボタンがIsCancel=Trueになっています。
ですので、Enterを押すとテキストブロックにOKが表示され、Escapeを押すとCancelが表示されます。
テキストブロックの文字がCancelになっていますね。
escapeキー
escapeキーを押すと IsCancel=trueにしているescape(ync)を表示しているボタンのclickイベントが実行されます。
MessageBoxButton.YesNoCancelで表示しているメッセージボックスも デフォルトでYes、EscapeでCancelが選択されるようです。
OKのみ / YesNo
MessageBoxButton.OKのメッセージボックスは デフォルト・Escape共にtrueのようで、Enter・escapeどちらでもokが選択されます。
MessageBoxButton.YesNoのメッセージボックスは デフォルトでyesが選択されるようですが、Escapeでは反応がありません。
IsCancelというプロパティ名なので、キャンセルボタンがない場合は基本的にはtrueにしないほうがいいようです。
escapeを押してもcloseしてくれないメッセージボックス。
show NoDefWin(自作window)
show NodefWinボタンで表示する自作windowはボタンを2つ並べているwindowです。
<!--一部のみ--><Grid.ColumnDefinitions><ColumnDefinitionWidth="*"></ColumnDefinition><ColumnDefinitionWidth="*"></ColumnDefinition></Grid.ColumnDefinitions><TextBlockText="okでシャットダウンします"/><GridGrid.Column="0"><ButtonContent="ok"Width="100"Height="30"Click="Button_Close"/></Grid><GridGrid.Column="1"><ButtonContent="cancel"Width="100"Height="30"Click="Button_Close"/></Grid>
Button_Closeイベントはthis.Close()のみです。
IsDefaultもIsCancelもtrueにしていないので、Enter・Escapeキーを押しても反応がありません。まぁ、当然ですね。
ということで自作windowでOK・キャンセルボタンを設置するときはIsDefaultとIsCancelプロパティを使ってあげようというお話でした。
まとめ
windowsの仕様に倣うのであれば、okタイプのボタンならDefault=Trueにして、キャンセルのボタンならIsCancel=Trueにしたほうがいいと改めて感じました。
・・・評価仕様でこういう確認見たことないな。