No more Death March

あるSEのチラシの裏 C# WPF

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を無効化すれば良いが、全角入力を受け付ける場合は注意が必要。

 以下参考
IMEで変換状態中でもTextBox.TextChangedが発生する | 泥庭

Textプロパティへの書き込み

 コード側でTextBoxのTextプロパティを書き換えられた場合、これはTextChangedイベントで検出する必要がある。全てのチェックをTextChangedイベントで完結させることも出来るが、キャレットの復元やテキストの復元まで考慮すると複雑なロジックになってしまいがち。また、MVVMで開発している場合、ViewModelとの余計な通信が発生する原因にもなるので役割を分担して対応したいところ。