読者です 読者をやめる 読者になる 読者になる

亀岡的プログラマ日記

京都のベッドタウン、亀岡よりだらだらとお送りいたします。

WPFの日本語入力は鬼門っぽい

文字数制限をかけるテキストボックスを作成しているんですが、これはかなり魔物ですな。
ちなみに文字数制限はよくある「ShiftJIS」型の文字数制限です。半角全角を区別する的なね。

最初はイベントでやるべえ、と思ってPreviewKeyDownでさくっとイケルと思ったのですよ。

        /// <summary>
        /// テキスト入力直前のイベント
        /// </summary>
        /// <param name="sender">イベントソース</param>
        /// <param name="e">イベント引数</param>
        private void TextBoxPreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            var textBox = sender as TextBox;   //<- ※
            //255文字以上なら弾くよ
            if (CalcSJISLength(textBox.Text + e.Text) > 255)
            { e.Handled = true; }
        }

        /// <summary>
        /// ShiftJISに文字列を変換して長さを取得します
        /// </summary>
        /// <param name="p">入力文字列</param>
        /// <returns>長さ</returns>
        private int CalcSJISLength(string p)
        {
            return Encoding.GetEncoding("shift-jis").GetByteCount(p);
        }

これがうまく動かない。
いや、英語なら所望の動作なんですよ。英語だとShiftJISとか意味ないからそれはそれで不毛だけど。

日本語だと、上のソースの※の場所で、すでにテキストが入力されちゃってるんだよねえ・・・
Previewなのに。
いろいろ探ると既知の不具合っぽい。
500 -内部サーバー エラーです。

TextBoxで入力にフィルターをしたい。

んで。

□投稿者/ 中博俊@管理人 (2回)-(2008/06/10(Tue) 20:41:14)

んーイベントではそうですが、バインドすれば望みの結果をとれると思いますけど。

これでなんとかなる・・・かな。
今から挑戦します。

結論:むりっぽ

えーっと。
バインディングタイミングをPropertyChangedにするとですね、バインドした時点ではテキストが入っていません(涙)
もう訳がわかんない.日本語怖い日本語怖い・・・

もう一度実験:やっぱり無理っぽ

PropertyChangedではなくExplicitにして、TextChangedでアップデートかけてみた.

var bind = (sender as TextBox).GetBindingExpression(TextBox.TextProperty);
bind.UpdateSource();

今度は変換中の値がどんどん入ってくるでござるの巻。
もう無理。かゆ。うま。