[VB.NET] [WPF] TextBox を選択したときに、自動でテキストを全選択させる方法

2013年11月30日

 WPF の TextBox をマウスでクリックして選択した場合、クリックした箇所に近い文字間にキャレットが挿入されます。
 そうじゃなくて、IE の URL を入力するところのように、テキストを全選択したい…というケースの実装方法について。

 具体的には、以下のような流れで処理しています。

  • 左マウスボタンを押したとき、まだフォーカスを持っていなければ、フォーカスを強制的に得る。
  • そして、イベントチェーンを切断する。(e.Handled = True)
  • フォーカスイベントで、テキストを全選択する。

 コードビハインド側

Class MainWindow 

  Private Sub TextBox_PreviewMouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
    Dim t = CType(sender, TextBox)

    If (t.IsFocused = False) Then
      t.Focus()
      e.Handled = True

    End If

  End Sub

  Private Sub TextBox_GotFocus(sender As Object, e As RoutedEventArgs)
    Dim t = CType(sender, TextBox)

    t.SelectAll()

  End Sub

End Class

 XAML側

<Window ....
  <Window.Resources>
    <Style TargetType="TextBox">
      <EventSetter Event="PreviewMouseLeftButtonDown" Handler="TextBox_PreviewMouseLeftButtonDown"/>
      <EventSetter Event="GotFocus" Handler="TextBox_GotFocus"/>
    </Style>
    
  </Window.Resources>
  <StackPanel>
    <TextBox Text="AAAA"/>
    <TextBox Text="BBBB"/>
    <TextBox Text="CCCC"/>
    <TextBox Text="DDDD"/>
  </StackPanel>
</Window>

 なんでこんな処理になるかというと、デフォルトでは、以下の動きをしているようです。(予想/根拠なし)

  1. 左クリックする。
  2. テキストボックスにフォーカスが与えられる。そして、フォーカスが与えられた段階ではキャレットはテキストの先頭にいる。
  3. その後、クリックした近辺にキャレットを移動する。(=MouseLeftButtonDownイベントのタイミング?)

 つまり、2. のフォーカスを取得した段階でテキストを全選択 (.SelectAll) しても、その後の 3. の処理で全選択が解除(=キャレットが設定)されてしまいます。

 このため、PreviewMouseLeftButtonDown イベントの段階でイベントチェーンを断ち切ることで、MouseLeftButtonDown イベントを抑止し、キャレットが移動することを阻止しています。
 阻止するのはそのテキストボックスが初めてフォーカスを得るとき(クリックしたときにフォーカスがない場合)のみです。でないと、マウスクリックでキャレットを移動させることそのものができなくなってしまいます。
 また、以後のイベントを抑止してしまうと、既定の TextBox に Focus を与える処理に届かなくなるので、イベントの抑止と同時にフォーカスを強制的に得るようにします。

 なお、PreviewMouseLeftButtonDown イベント(トンネル イベント)と MouseLeftButtonDown イベント(バブルイベント)の違いについては以下が詳しいです。

 http://msdn.microsoft.com/ja-jp/library/ms742806.aspx#how_event_processing_works

 参考) イベントの伝播
 






カテゴリー: Program, VB.NET, WPF

Follow comments via the RSS Feed | Leave a comment | Trackback URL

コメントを投稿する

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


«   »
 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org