バイト長で制限したいときもある(壱)。

C#は、内部のコードや文字列をUnicodeで持っている。その関係で、stringクラスが持つLengthプロパティは、バイト長ではなく、文字数を返す仕様となっている。では、バイト長をどうやって取得するか?というと、Shift_JISに変換した上でLengthを取得する方法が一般的になる。
using System;
using System.Text;

namespace TawamureDays {

public class Utils {

/// <summary>
/// 指定された文字列のバイト数を返します。
/// </summary>
/// <param name="str">指定文字列</param>
/// <returns>バイト数</returns>
public static long GetByteLength(string str) {
if (Utils.IsEmpty(str)) {
return 0;
}

//Shift_JISに変更してバイト数をカウントする
//Unicodeはどんな文字でも2バイトだった...
return Encoding.GetEncoding("Shift_JIS").GetByteCount(str);
}
}
}

ところで、TextBoxにはMaxLengthというプロパティがあり、これも例外なく文字数の制限となる。これを使ったところで、バイト長による制限を掛ける事はできない。
そもそも、なぜ今の御時世にバイト長?かというと、その制限を要求される項目が帳票に出力されるからだ。
帳票はいつの時代も、ペーパーレスだのエコだのと言われながらも、紙で必要とされる種類がある。だって、ハッキングされないし。ちゃんと保管していれば、なくならないし。業者のミスにより消される事もないし。電子データを保管するHDDなんかの耐用年数なんかとは比べ物にならない年数を保管できるし。受注伝票、納品書、製品仕様書等々。いつの時代も帳票は必要とされる。逆にこれが出力されないと、電子化する意味あんの?という気がする業務もあったりするし。
で、開発中の画面も、そういう帳票に出る項目があり、バイト長による制限を付与する必要がある。

・一番良いのは、制限以上の文字を入力できなくすることだ。
 →でも、MaxLengthは文字数による制限なので、完全とはいえない。
・次に良いのは、そのバイト数を超えたら、エラーにすることだ。
 →数値入力オンリーにしなくたって方法はある。かな。でやったようなValidationRuleクラスを使う。
次善策を作ることはできた。ただ、同僚から、「やっぱ制限かけませんか?」という話になって、バイト長による入力制限を調べることになった。現在は、まだ完全に制限できていない為、現在までのメモを列挙しておく。
・PreviewKeydownイベントでは、日本語入力を検知できない。
・以下の記事を参考にいいところまでは実装できたんだけど、不完全。
 (1)WPFのテキストボックスでバイト数単位での入力制限を行う
  ↑は、イベントハンドラの削除処理が記述されていないので、そのまま使うとメモリリークの元になる。
  更に、Google IMEと恐ろしいまでに相性が悪い(一撃でアプリを道連れに落ちる。再現率ほぼ100%)。
 (2)TextBox に長さ制限を設ける
  ただし、文字数による制限となっている。
 (3)IMEで変換状態中でもTextBox.TextChangedが発生する
  これは非常に勉強になりました。
 (4)Q028.WPF の TextBox.TextChanged イベントって IME の変換候補を選択しただけでも発生しますが、これって仕様でしょうか?
 (5)TextBox で添付ビヘイビアを使ったところ、IME と干渉するのか重大エラーが!
  (4)の記事にある「場合によっては重大なバグを引き起こすので」のところがリンク切れしていたので。
  Connectの方に移ったらしいんだけど、どうなったんだろ。WPF4では修正されないのかな。

・上記記事で使っているクラスのドキュメント
 TextCompositionクラス
 TextCompositionManagerクラス

・なにげにめんどくさいのは、テキスト貼り付けに対する制限だったりする。
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m