C# WPF PreviewTextInputで入力後のテキストを取得する。
とりあえずコード
private static void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { var textBox = sender as TextBox; if (textBox == null) return; var changed = textBox.Text .Remove(textBox.SelectionStart, textBox.SelectionLength) .Insert(textBox.SelectionStart, e.Text) ; }
・テキストボックスの選択範囲の文字列を消す。(Removeメソッドの部分)
・イベント引数から入力された文字列(e.Text)を選択位置に挿入する。(Insertメソッドの部分)
※自作ビヘイビアからの抜粋なのでメソッドはprivate static
注意しなければいけないこと
これだけで万事解決出来れば良いのだけど他にも気を付けなければいけないことある。
ペーストへの対応
DataObjectPastingイベントのハンドラーを使ってペースト時にチェックを処理を差し込んでやる必要がある。
イベントハンドラーの購読はDataObjectクラスのAddPastingHandlerメソッド、
購読の解除はDataObjectクラスのRemovePastingHandlerメソッドを使う。
DataObjectPastingイベントの購読と購読解除の例
// 購読開始 DataObject.AddPastingHandler(textBox, OnPasting); // 購読解除 DataObject.RemovePastingHandler(textBox, OnPasting);
先のPreviewTextInputの時と同じようにペーストした後のテキストを取得するなら以下のような具合になる。
private static void DataObject_Pasting(object sender, DataObjectPastingEventArgs e) { var textBox = sender as TextBox; if (textBox == null) return; var pasted = e.SourceDataObject.GetData(DataFormats.UnicodeText) as string; if (pasted == null) return; var changed = textBox.Text .Remove(textBox.SelectionStart, textBox.SelectionLength) .Insert(textBox.SelectionStart, pasted) ; }
IMEへの対応
WPFではIMEの入力途中であってもTextChangedイベントが発生する。半角文字の入力に限定したコントロールであれば、
フォーカス中にIMEを無効化すれば良いが、全角入力を受け付ける場合は注意が必要。
Textプロパティへの書き込み
コード側でTextBoxのTextプロパティを書き換えられた場合、これはTextChangedイベントで検出する必要がある。全てのチェックをTextChangedイベントで完結させることも出来るが、キャレットの復元やテキストの復元まで考慮すると複雑なロジックになってしまいがち。また、MVVMで開発している場合、ViewModelとの余計な通信が発生する原因にもなるので役割を分担して対応したいところ。