- PR -

数値型をソースとするTextBoxに一旦入れた後空白にしたい

投稿者投稿内容
island_town
ベテラン
会議室デビュー日: 2007/05/08
投稿数: 77
投稿日時: 2008-01-08 21:32
みなさんありがとうございます。
Validatingのソースは心当たりがあるので明日良く見てみます。
ソースはAllowDBNull=Trueの列です。
あとWindowsFormでVisual Studio 2005です。

[ メッセージ編集済み 編集者: island_town 編集日時 2008-01-08 21:34 ]
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2008-01-08 21:35
Nullをセットしたいのだから、Not Nullは違うだろ、と反論がきそう。
先回りしておくと、その入力値のバインド先は主キーで、未入力なら追加(そして児童採番)
入力されたら更新、したいんじゃないかなと。
スレ主の追記求む。

追記:
あ、Null可なのね。
先の投稿はぜんぜん関係ないわ。


[ メッセージ編集済み 編集者: かずくん 編集日時 2008-01-08 21:38 ]
island_town
ベテラン
会議室デビュー日: 2007/05/08
投稿数: 77
投稿日時: 2008-01-08 21:36
主キー列ではなく普通の列です。
island_town
ベテラン
会議室デビュー日: 2007/05/08
投稿数: 77
投稿日時: 2008-01-09 09:57
テスト用のテーブルTable1
ID tinyint PrimaryKey
Num int
を作りデータセットを作り
詳細形式でフォームにバインドしてみました。
ソースは以下の通りです。

コード:

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void table1BindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.table1BindingSource.EndEdit();
this.table1TableAdapter.Update(this.customerDataSet.Table1);

}

private void Form1_Load(object sender, EventArgs e)
{
this.table1TableAdapter.Fill(this.customerDataSet.Table1);

}
}



やっぱりNumフィールドで同じ問題が発生しました。

なおAutoValidateプロパティをEnableAllowFocusChangeにすると
確かにフォーカスは移動しますが
今度はValidatingでe.Cancel = true;にしても
数値でない文字列を入れても
フォーカスが移動してしまいます。

どうなっているのでしょうか。
よろしくお願いします。


[ メッセージ編集済み 編集者: island_town 編集日時 2008-01-09 10:12 ]

[ メッセージ編集済み 編集者: island_town 編集日時 2008-01-09 14:22 ]
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2008-01-09 10:44
空回りしっぱなしなので、適当に聞き流してください。

おそらくデータセットデザイナまたはデーソースの追加を介して型付データセットを作っていると思います。
データセットデザイナで確認してもらえば分かりますが、おそらくNumの型はSystem.Int32となってるはずです。
System.String以外は、NullValueプロパティに(Throw exception)しか指定できないみたいです。

内部的に例外が発生して、フォーカスアウトを阻害しているのかもしれません。

引用:

なおAutoValidateプロパティをEnableAllowFocusChangeにすると
確かにフォーカスは移動しますが
今度はValidatingでe.Cancel = true;にしても
数値でない文字列を入れても
フォーカスが移動してしまいます。


Windows フォームにおけるユーザー入力の検証 (Windows フォーム)(microsoft.com)より仕様です。
しかしユーザビリティを考慮した場合、AutoValidateプロパティをEnableAllowFocusChangeにしたほうがよいように思えます。

ただし、その場合、Validationgで入力エラーが見つかった場合は、ErrorProviderでエラー内容を表示するようにし、
またDB更新は、ValidateChildren()を通過した場合のみ行うようにする必要があります。

この辺の話は、過去ログ見てもらった方がよいかと。
私も洗脳されたくちなので。

追記:
AutoValidateプロパティがEnableAllowFocusChange出ない場合、ユーザビリティとして何が悪い可といえば、フォーカス移動したいのに出来ないのでストレスがたまるということ(個人的に)
アラートが出て、フォーカス抜けれないUIも大っ嫌い(個人的に)。

追記2:
Windows フォームにおけるユーザー入力の検証 (Windows フォーム)(microsoft.com)にも書かれていますが、
引用:

EnableAllowFocusChange を割り当てた場合は、イベントをキャンセルしても Validated イベントは発生せず、フォーカスはそのまま新しいコントロールに移ります。


Windows フォームにおけるユーザー入力の検証 (Windows フォーム)より引用

ということに注意する必要があります。
これは、Bindingのデータソース更新モード(DataSourceUpdateMode)がOnValidationの場合、Null値が反映せず、前回の値のままということを意味しています。

[ メッセージ編集済み 編集者: かずくん 編集日時 2008-01-09 10:48 ]

[ メッセージ編集済み 編集者: かずくん 編集日時 2008-01-09 10:57 ]
island_town
ベテラン
会議室デビュー日: 2007/05/08
投稿数: 77
投稿日時: 2008-01-09 13:15
AutoValidateプロパティをEnableAllowFocusChangeにして
テーブルにAge tinyint列を追加し
Age列にValidatingイベントを追加してe.Cancel = true;のサンプルを作り
保存時にValidateChildren()を呼び出してみました。

コード:

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void table1BindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.BeforeSave();
if (this.ValidateChildren() == false)
{
MessageBox.Show("入力項目にエラーがあります");
return;
}
this.table1BindingSource.EndEdit();
this.table1TableAdapter.Update(this.customerDataSet.Table1);
MessageBox.Show("更新しました");
}

private void BeforeSave()
{
String Value;
Value = this.numTextBox.Text;
if(Value.Equals(""))
((DataRowView)this.table1BindingSource.Current)["Num"] = DBNull.Value;
Value = this.ageTextBox.Text;
if(Value.Equals(""))
((DataRowView)this.table1BindingSource.Current)["Age"] = DBNull.Value;
}

private void Form1_Load(object sender, EventArgs e)
{
this.table1TableAdapter.Fill(this.customerDataSet.Table1);
}

private void ageTextBox_Validating(object sender, CancelEventArgs e)
{
String Value = ((TextBox)sender).Text;
if (Value.Equals(""))
{
this.errorProvider1.SetError(this.ageTextBox, "");
return;
}
int Val;
try
{
Val = Int32.Parse(Value);
if (Val > 100)
{
this.errorProvider1.SetError(this.ageTextBox,"数値が範囲外です");
e.Cancel = true;
}
else
{
this.errorProvider1.SetError(this.ageTextBox, "");
}
}
catch (Exception)
{
this.errorProvider1.SetError(this.ageTextBox, "形式が不正です");
e.Cancel = true;
}
}

private void numTextBox_Validating(object sender, CancelEventArgs e)
{
String Value = ((TextBox)sender).Text;
if (Value.Equals(""))
{
return;
}
}



やってみましたが数値を空白に直すとValidateChildern()でエラーを返します。
方法がないようです。
どうしたら良いのでしょうか。

あとどなたかコードの貼り付け方を教えてください。


[ メッセージ編集済み 編集者: island_town 編集日時 2008-01-09 13:41 ]
まるく
大ベテラン
会議室デビュー日: 2004/01/09
投稿数: 181
投稿日時: 2008-01-09 13:37
引用:

island_townさんの書き込み (2008-01-09 13:15) より:
あとどなたかコードの貼り付け方を教えてください。


http://www.atmarkit.co.jp/bbs/phpBB/faq-japanese.php#bbcode
island_town
ベテラン
会議室デビュー日: 2007/05/08
投稿数: 77
投稿日時: 2008-01-09 13:43
ありがとうございます。

スキルアップ/キャリアアップ(JOB@IT)