< RadioButton を ListBox で実装する 4 | インストールされている .NET Framework のバージョンをチェックするスクリプト >

July 2, 2009

TextBox に長さ制限を設ける

WPF の TextBox の MaxLength が TSF 環境下で使い物にならない件ですが、Feedback への Microsoft からの回答によると、次期バージョンで何とかなる、のかな?

とはいえ、今抱えてる案件は .NET Framework 3.5 で対応しなきゃいけないわけで。添付プロパティを使って無理矢理対応してみました。時間があったらまた詳しく書きます。
※ バイト数単位で切ることはできません。文字数単位です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace MaxLength
{
    public class LengthCheck
    {
        /// <summary>
        /// 指定された System.Windows.Controls.TextBox から LengthCheck.MaxLength 添付プロパティの値を取得します。
        /// </summary>
        /// <param name="textBox">プロパティ値の読み取り元の要素。</param>
        /// <returns>LengthCheck.MaxLength 添付プロパティの値。</returns>

        public static int GetMaxLength (TextBox textBox)
        {
            return (int) textBox.GetValue (MaxLengthProperty);
        }


        /// <summary>
        /// LengthCheck.MaxLength 添付プロパティの値を、指定された System.Windows.Controls.TextBox に設定します。
        /// </summary>
        /// <param name="textBox">添付プロパティを設定する要素。</param>
        /// <param name="value">設定するプロパティ値。</param>

        public static void SetMaxLength (TextBox textBox, int value)
        {
            textBox.SetValue (MaxLengthProperty, value);
        }


        /// <summary>
        /// LengthCheck.MaxLength 添付プロパティを識別します。
        /// </summary>

        public static readonly DependencyProperty MaxLengthProperty =
            DependencyProperty.RegisterAttached ("MaxLength", typeof (int), typeof (LengthCheck), new FrameworkPropertyMetadata (0, new PropertyChangedCallback (MaxLengthProperty_Changed)));


        /// <summary>
        /// LengthCheck.MaxLength 添付プロパティの値が変更された際に、コントロール側にイベントハンドラを設定します。
        /// </summary>
        /// <param name="d">添付プロパティが設定された要素。</param>
        /// <param name="e">イベントの引数。</param>

        static void MaxLengthProperty_Changed (DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var textBox = d as TextBox;

            if (textBox != null)
            {
                try
                {
                    int newValue = (int) e.NewValue;

                    // MaxLength プロパティを設定する。
                    textBox.MaxLength = newValue;
                    if (newValue == 0)
                    {
                        // イベントハンドラ解除
                        TextCompositionManager.RemoveTextInputStartHandler (d, new TextCompositionEventHandler (OnTextInputStart));
                        TextCompositionManager.RemovePreviewTextInputHandler (d, new TextCompositionEventHandler (OnPreviewTextInput));
                    }
                    else
                    {
                        // イベントハンドラ設定
                        TextCompositionManager.AddTextInputStartHandler (d, new TextCompositionEventHandler (OnTextInputStart));
                        TextCompositionManager.AddPreviewTextInputHandler (d, new TextCompositionEventHandler (OnPreviewTextInput));
                    }
                }
                catch
                {// 無視する
                }
            }
        }


        /// <summary>
        /// 新しい TextComposition が開始されると発生します。
        /// </summary>
        /// <param name="sender">イベント ハンドラがアタッチされているオブジェクト。</param>
        /// <param name="e">イベントのデータ。</param>

        static void OnTextInputStart (object sender, TextCompositionEventArgs e)
        {
            // IME が ON の場合は MaxLength を無効にする。

            var ime = InputMethod.Current;
            var textBox = e.Source as TextBox;
            if (textBox != null && ime.ImeState == InputMethodState.On)
                textBox.MaxLength = 0;

        }


        /// <summary>
        /// TextComposition が完了したときに発生します。
        /// </summary>
        /// <param name="sender">イベント ハンドラがアタッチされているオブジェクト。</param>
        /// <param name="e">イベントのデータ。</param>

        static void OnPreviewTextInput (object sender, TextCompositionEventArgs e)
        {
            // 入力確定時に MaxLength を再設定する。

            var ime = InputMethod.Current;
            var textBox = e.Source as TextBox;
            if (textBox != null && ime.ImeState == InputMethodState.On)
            {
                textBox.MaxLength = GetMaxLength (textBox);
                textBox.Text = textBox.Text.Substring (0, GetMaxLength (textBox));
            }
        }
    }
}

現象については以下
WPF: 日本語入力時、 テキストボックスに Maxlength 以下の長さの文字列が入力できない | Microsoft Connect
Re[2]: WPFのTextChangeイベント
biac の それさえもおそらくは幸せな日々@nifty: [.NET] フィードバック - WPF: テキストボックスに Maxlength の長さの日本語文字列が入力できない

トラックバック

このエントリーにトラックバック:
http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/2397

コメント

コメントする

※ コメントスパム対策のため、コメント本文はおはよう、こんにちわ、こんばんわのいずれかより始めるようにしてください。

name:
email:

※ 必要ですが、表示しません。

url:
情報を保存する ?