DOBON.NET DOBON.NETプログラミング掲示板過去ログ

数字とバックスペース以外の入力を無効にしたTextBox

環境/言語:[Visual Studio 2010 Express C#]
分類:[.NET]

http://dobon.net/vb/dotnet/control/numerictextbox.html

上記ページに記載されていたNumericTextBoxクラスを作成し、
デザイナーでフォームに貼り付けてデザイナーを閉じた後、
再度デザイナーを開こうとしたところ、エラーとなり開けなくなりました。

クラス定義では
private char[] _allowKeyChars = new char[] { '\b' };
/// <summary>
/// 数字以外で入力が可能な文字
/// </summary>
public char[] AllowKeyChars
{
get { return this._allowKeyChars; }
set { this._allowKeyChars = value; }
}
のようにAllowKeyCharsプロパティの定義を行っており、
「'\b'」を初期値として設定しております。

貼り付け先のフォームのコードを開いたところ、以下のようになっておりました。
private void InitializeComponent()
{
this.numericTextBox1 = new test1.NumericTextBox();
this.SuspendLayout();
//
// numericTextBox1
//
this.numericTextBox1.AllowKeyChars = new char[] {
''};

char型の配列の要素に長さ0の文字「''」を設定するようなコードとなっているのが、エラーの原因だと思われますが、ユーザーコントロールのプロパティにエスケープ文字は使用してはいけないのでしょうか?
回避策があればご教授ください。
■No32209に返信(スパゲッティさんの記事)
> char型の配列の要素に長さ0の文字「''」を設定するようなコードとなっているのが、エラーの原因だと思われますが、ユーザーコントロールのプロパティにエスケープ文字は使用してはいけないのでしょうか?
> 回避策があればご教授ください。
>
ここの文章の意味は理解できないけど、きっと'\0'とかしたいのでしょうか?
エスケープ文字 ⇒ \(円記号)

単純に
char [] x = new char[]{''}
だとコンパイルエラーになっているはず。

デザイナーで開けなくなったのは、デザイナーで表示するためにフォームインスタンス処理を実行しようとしてInitializeComponentで例外エラーが発生しているためだと思う。
■No32213に返信(aさんの記事)
> ■No32209に返信(スパゲッティさんの記事)
>>char型の配列の要素に長さ0の文字「''」を設定するようなコードとなっているのが、エラーの原因だと思われますが、ユーザーコントロールのプロパティにエスケープ文字は使用してはいけないのでしょうか?
>>回避策があればご教授ください。
>>
> ここの文章の意味は理解できないけど、きっと'\0'とかしたいのでしょうか?
>
「AllowKeyChars で追加されている文字を入力可能にする」というのを取り消したいのなら、そこの領域を書き換えるのではなく、AllowKeyChars の使用有無プロパティを実装した方が意味が通りそう。
■No32213に返信(aさんの記事)
> char [] x = new char[]{''}
> だとコンパイルエラーになっているはず。

a さんは「''」だと誤解されたようですが、
スパゲッティさんが書いたのは「''」ですね。
(掲示板の都合上判別しにくいですが、いわゆる ^H の文字です)


> InitializeComponentで例外エラーが発生しているためだと思う。
実際に試してみると分かりますが、文法的には問題は生じていません。
コンパイルしてみれば、問題なく実行されます。


■No32209に返信(スパゲッティさんの記事)
> ユーザーコントロールのプロパティにエスケープ文字は使用してはいけないのでしょうか?

エスケープ文字かどうかは関係ありませんし、
現象としてはユーザーコントロールに限りません。

ただの Form や TextBox に対して、Text プロパティに、
一部の制御文字を含めただけで同様の問題が発生します。
もちろん、一般的な \r、\n、\t などは問題なく処理されます。

ちなみに VB では、制御文字を含んでいたとしても問題は出ないようです。


> 回避策があればご教授ください。
「配列を使わない」のが、もっとも簡単かと思います。

たとえば、AllowKeyChars を
 private List<char> _allowKeyChars = new List<char>(new char[] { '\b' });
 public List<char> AllowKeyChars {…}
に変更してやれば、データはデザイナコードからリソース(resx)側へと
移動するため、今回の問題を避けることができます。

ただし、AllowKeyChars のデータ型を変更することになりますし、
OnKeyPress の判定を AllowKeyChars.Contains(e.KeyChar) に
変更する必要は生じます。
■No32215に返信(魔界の仮面弁士さんの記事)
> ■No32213に返信(aさんの記事)
>>char [] x = new char[]{''}
>>だとコンパイルエラーになっているはず。
>
> a さんは「''」だと誤解されたようですが、
> スパゲッティさんが書いたのは「''」ですね。
> (掲示板の都合上判別しにくいですが、いわゆる ^H の文字です)
>
勘違いしてました。ごめんなさい。
VS上でも^H入っているようには見えなかった。orz

外部から許可するキーコードを追加する必要がないならセッターをコメントアウトしても回避できるみたいです。
ただ、今後の拡張性を考慮すると魔界の仮面弁士さんが書かれているようにListに変更するのがいいですね。
■No32216に返信(aさんの記事)
> ■No32215に返信(魔界の仮面弁士さんの記事)
>>■No32213に返信(aさんの記事)
> >>char [] x = new char[]{''}
> >>だとコンパイルエラーになっているはず。
>>
>>a さんは「''」だと誤解されたようですが、
>>スパゲッティさんが書いたのは「''」ですね。
>>(掲示板の都合上判別しにくいですが、いわゆる ^H の文字です)
>>
> 勘違いしてました。ごめんなさい。
> VS上でも^H入っているようには見えなかった。orz
aさん、魔界の仮面弁士さん回答有難うございます。
私自身、空文字だと思ってました……
空文字でなかったため、文法上は問題なくコンパイルできるのですね。

> 外部から許可するキーコードを追加する必要がないならセッターをコメントアウトしても回避できるみたいです。
> ただ、今後の拡張性を考慮すると魔界の仮面弁士さんが書かれているようにListに変更するのがいいですね。
Listにする方法だとリソース側にコードが移動するのですね。
今回は'\b'をAllowKeyChars入れる必要がなかったので、
private char[] _allowKeyChars;
として、初期値は入れないことにしました。
その上で、OnKeyPressの条件判定を
if ((e.KeyChar < '0' || '9' < e.KeyChar) &&
(this.AllowKeyChars == null || Array.IndexOf(this.AllowKeyChars, e.KeyChar) < 0) &&
e.KeyChar != '\b')
{
e.Handled = true;
}
のように変更しました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板