トップ回答者
[自動セル移動]時のセルへの入力の仕方?

質問
-
いつも的確なアドバイスをいただいておりますことに感謝申し上げます。
たび重ねての質問で恐縮ですがよろしくお願いします。
《質問1》
教えていただきたいことは,例えばRow=3,Col=7(Rowの値は変動します)のとき,dataGridView1[Col, Row].Value = "100";でセルの値を変更できないのですが,どの様に対処しなければいけないのかということです。《質問2》
下のKeyPressイベントで
ア[Enterキー] イ[BackSpaceキー] ウ[↓キー]
の検出(e.KeyChar==”???”)をどのように書いて実行するのでしょうか?下のコードは,生徒のテストの得点の入力処理(完成途中)の場面です。
テストの得点を2桁入力すると自動的にセルを移動させています。
百点の場合は,”-”を入力しそれを”100”に変更しようとして,つまづいています。
//KeyPress 入力文字数
private int Cnt = 0;private void SendDown()
{
SendKeys.Send("{DOWN}");
Cnt = 0;
}private void EditingControl_KeyPress(object sender,
KeyPressEventArgs e)
{
int Row = dataGridView1.CurrentCell.RowIndex;
int Col = dataGridView1.CurrentCell.ColumnIndex;
string InpChr = e.KeyChar.ToString();Regex rgx = new Regex("[^-/0-9]");
//数字以外
if (rgx.IsMatch(e.KeyChar.ToString()))
{
InpChr = "";
e.Handled = true;
}
//数字
else
{
Cnt++;
switch (Cnt)
{
case 1:
if (InpChr == "-") //百点
{
//SendKeys.Send("{DOWN}");
//SendKeys.Send("{UP}");
dataGridView1[Col, Row].Value = "100";
SendDown();
}
if (InpChr == "/") //欠席
{
SendDown();
}
break;
case 2:
SendDown();
break;
}
}
}
回答
-
zen73 さんからの引用
「オーバーライド」する方法は,よく理解できないためいつも避けてきた方法です。
・
・
(中略)
・
・
よくわからないのですが,下のようにするのとはちがうことをおっしゃっているようですが・・・・。
if (InpChr == "-") //百点
{
myDataGridViewTextBoxCell myCell = new myDataGridViewTextBoxCell();
myCell.KeyEntersEditMode(?eではないようです?);
SendDown(); ↑なんとするのでしょうか
}
オーバーライドは、それほど難しい概念ではありません。例えば、public class myDataGridViewTextBoxCell : DataGridViewTextBoxCell { }
とした場合、myDataGridViewTextBoxCellクラスの中身は空なので、何も無いのと同じでしょうか? いえ、そんなことはないですよね。DataGridViewTextBoxCellクラスを継承しているので、myDataGridViewTextBoxCellクラスはDataGridViewTextBoxCellクラスと全く同じ内容になっています。しかしこれでは継承する意味がありません。myDataGridViewTextBoxCellクラスでは、DataGridViewTextBoxCellクラスのあるメソッドの内容を変更したいと思います。そこでオーバーライドが登場します。ここでは変更したいメソッドをKeyEntersEditModeとします。
public class myDataGridViewTextBoxCell : DataGridViewTextBoxCell { public override bool KeyEntersEditMode(KeyEventArgs e) { if (e.KeyCode == Keys.OemMinus) { this.SetValue(this.DataGridView.CurrentCell.RowIndex, 100); return false; } return base.KeyEntersEditMode(e); } }
つまり、myDataGridViewTextBoxCellクラスにおいてKeyEntersEditModeを定義、すなわちオーバーライドしなければ、KeyEntersEditModeはDataGridViewTextBoxCellクラスのものが使われ、myDataGridViewTextBoxCellクラスでKeyEntersEditModeを定義、すなわちオーバーライドすれば、myDataGridViewTextBoxCellクラスにおけるKeyEntersEditModeメソッドの内容は、その定義、すなわちオーバーライドされた中身になります。
今回の例で言えば、DataGridViewTextBoxCellクラスにおいて、KeyEntersEditModメソッドは、-を普通のキー入力として扱い、DataGridViewをEditモードへ移行させます。ところが、myDataGridViewTextBoxCellクラスのKeyEntersEditModメソッドは、-を特殊キーとして扱い、Editモードへ移行せず、-の代わりに100が入力されたものとして扱います。
DataGridViewの一つ一つのセルは、通常、DataGridViewTextBoxCellクラスによって構成されています。今回は、これをmyDataGridViewTextBoxCellクラスに置き換えてしまおうという発想なのです。DataGridViewTextBoxCellクラスさんさようなら、myDataGridViewTextBoxCellクラスさん、こんにちはという感じです。myDataGridViewTextBoxCellクラスを定義すると(今のフォームクラスのすぐ下に、続けてこのDataGridViewTextBoxCellクラスの定義を書いてください。同じ名前空間の定義の中に書いてください)、DataGridViewのデザイン画面において、DataGridViewのプロパティからColumnsのコレクションを開き、列の編集画面で、ColumnTypeがDataGridViewTextBoxCellになっていると思いますが、これをmyDataGridViewTextBoxCellに変更できるようになっているはずですので、myDataGridViewTextBoxCellに変更して下さい。これで、この列のセルは、-を入力すると100が入るようになります。
もし、DataGridViewのデザイン画面で列の定義をされておらず、コードで定義されているのでしたら、
DataGridViewTextBoxCell myCell = new DataGridViewTextBoxCell();
を
myDataGridViewTextBoxCell myCell = new myDataGridViewTextBoxCell();
と変更するだけでOKです。
いろいろと書きましたが、うまく伝わりましたでしょうか?
オーバーライドとは、あるクラスの一部だけを変えたい場合に、そのクラスを継承したクラスで、変えたい部分だけを定義してあげたものと考えればわかりやすいのではないでしょうか? 継承したクラスにおいて、定義しない部分は、継承元のクラスのものが使われます。 変えたい部分だけを定義することによって、簡単にその部分だけ違う振る舞いをするクラスを作成できるという、実によくできているとは思いませんか?
すべての返信
-
いくつかポイントがありますので、順にお話します。
まず、KeyPressイベントとKeyDownイベントの違いを理解して下さい。大まかに言って、KeyPressイベントはアルファベットなどの文字キーが押された時に発生するイベントで、KeyDownはキーが押された時に発生するイベントです。ただ、いくつか例外があります。以下が参考になると思います。
第21回 マウス・キーボードからの入力
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard21.htm次に、コントロールに入力されたキーは、どのキーも同様に扱われるわけではありません。どのキーをどう扱うのかは、コントロールによって異なります。詳しくは以下を参考にして下さい。
Windowsアプリケーションで方向キーなどの特殊キーを処理するには? http://www.atmarkit.co.jp/fdotnet/dotnettips/241windlgkey/windlgkey.html
Windowsアプリケーションでキー処理が行われる順序は?
http://www.atmarkit.co.jp/fdotnet/dotnettips/243winkeyproc/winkeyproc.htmlさて、ようやく本題です。 -を押したときに、dataGridView1[Col, Row].Value = "100";で入力できないのは、DataGridViewが-を普通の入力キーとして扱い、Editモードに入っているからです。この時、DataGridViewTextBoxEditingControlが表示されてキー入力を処理しています。 そうであれば、-を普通の入力キーとして扱わなければ良いわけで、ProcessDialogKeyが頭に浮かびます。しかし、DataGridViewTextBoxCellではこれをオーバーライドできるように用意されていません。代わりにKeyEntersEditModeが用意されています。こいつをオーバーライドしてfalseを返せば、DataGridViewはEditモードへ入りません。
public class myDataGridViewTextBoxCell : DataGridViewTextBoxCell { public override bool KeyEntersEditMode(KeyEventArgs e) { if (e.KeyCode == Keys.OemMinus) { this.SetValue(this.DataGridView.CurrentCell.RowIndex, 100); return false; } return base.KeyEntersEditMode(e); } }
としてあげて、これをDataGridViewのカラムの使って下さい。このクラスを定義すると、デザインモードのColumnsの設定からも指定できるようになります。
あと、
zen73 さんからの引用
下のKeyPressイベントで
ア[Enterキー] イ[BackSpaceキー] ウ[↓キー]
の検出(e.KeyChar==”???”)をどのように書いて実行するのでしょうか?
についてですが、実際にそのキーを押してみて、KeyPressイベントでSystem.Diagnostics.Debug.WriteLineで表示させてみると良いでしょう。もちろん、ブレークポイントで止めて調査してもOKです。この辺りもちょっとしたテクニックです。上の3つのキーのうち、KeyPressイベントが起きるのは、イだけでしょう。しかも、DataGridViewがEditモードの時だけだと思います。 -
trapemiya さんからの引用 -を押したときに、dataGridView1[Col, Row].Value = "100";で入力できないのは、DataGridViewが-を普通の入力キーとして扱い、Editモードに入っているからです。
「オーバーライド」する方法は,よく理解できないためいつも避けてきた方法です。自分なりにEditモードから抜け出す方法を考えてみました。
if (InpChr == "-") //百点
{
CellChrSet(Col, Row, "100");
SendDown();
}
private void CellChrSet(int Col, int Row, string CellChr)
{
dataGridView1.CurrentCell = dataGridView1[Col + 1, Row];
dataGridView1[Col, Row].Value = CellChr;
SendKeys.Send("{LEFT}");
}trapemiya さんからの引用 これをDataGridViewのカラムの使って下さい。このクラスを定義すると、デザインモードのColumnsの設定からも指定できるようになります。
よくわからないのですが,下のようにするのとはちがうことをおっしゃっているようですが・・・・。
if (InpChr == "-") //百点
{
myDataGridViewTextBoxCell myCell = new myDataGridViewTextBoxCell();
myCell.KeyEntersEditMode(?eではないようです?);
SendDown(); ↑なんとするのでしょうか
}trapemiya さんからの引用 上の3つのキーのうち、KeyPressイベントが起きるのは、イだけでしょう。しかも、DataGridViewがEditモードの時だけだと思います。
アウ時の処理は教えていただいたdataGridView1_CellValueChangedでやってみようと思います。 -
zen73 さんからの引用
「オーバーライド」する方法は,よく理解できないためいつも避けてきた方法です。
・
・
(中略)
・
・
よくわからないのですが,下のようにするのとはちがうことをおっしゃっているようですが・・・・。
if (InpChr == "-") //百点
{
myDataGridViewTextBoxCell myCell = new myDataGridViewTextBoxCell();
myCell.KeyEntersEditMode(?eではないようです?);
SendDown(); ↑なんとするのでしょうか
}
オーバーライドは、それほど難しい概念ではありません。例えば、public class myDataGridViewTextBoxCell : DataGridViewTextBoxCell { }
とした場合、myDataGridViewTextBoxCellクラスの中身は空なので、何も無いのと同じでしょうか? いえ、そんなことはないですよね。DataGridViewTextBoxCellクラスを継承しているので、myDataGridViewTextBoxCellクラスはDataGridViewTextBoxCellクラスと全く同じ内容になっています。しかしこれでは継承する意味がありません。myDataGridViewTextBoxCellクラスでは、DataGridViewTextBoxCellクラスのあるメソッドの内容を変更したいと思います。そこでオーバーライドが登場します。ここでは変更したいメソッドをKeyEntersEditModeとします。
public class myDataGridViewTextBoxCell : DataGridViewTextBoxCell { public override bool KeyEntersEditMode(KeyEventArgs e) { if (e.KeyCode == Keys.OemMinus) { this.SetValue(this.DataGridView.CurrentCell.RowIndex, 100); return false; } return base.KeyEntersEditMode(e); } }
つまり、myDataGridViewTextBoxCellクラスにおいてKeyEntersEditModeを定義、すなわちオーバーライドしなければ、KeyEntersEditModeはDataGridViewTextBoxCellクラスのものが使われ、myDataGridViewTextBoxCellクラスでKeyEntersEditModeを定義、すなわちオーバーライドすれば、myDataGridViewTextBoxCellクラスにおけるKeyEntersEditModeメソッドの内容は、その定義、すなわちオーバーライドされた中身になります。
今回の例で言えば、DataGridViewTextBoxCellクラスにおいて、KeyEntersEditModメソッドは、-を普通のキー入力として扱い、DataGridViewをEditモードへ移行させます。ところが、myDataGridViewTextBoxCellクラスのKeyEntersEditModメソッドは、-を特殊キーとして扱い、Editモードへ移行せず、-の代わりに100が入力されたものとして扱います。
DataGridViewの一つ一つのセルは、通常、DataGridViewTextBoxCellクラスによって構成されています。今回は、これをmyDataGridViewTextBoxCellクラスに置き換えてしまおうという発想なのです。DataGridViewTextBoxCellクラスさんさようなら、myDataGridViewTextBoxCellクラスさん、こんにちはという感じです。myDataGridViewTextBoxCellクラスを定義すると(今のフォームクラスのすぐ下に、続けてこのDataGridViewTextBoxCellクラスの定義を書いてください。同じ名前空間の定義の中に書いてください)、DataGridViewのデザイン画面において、DataGridViewのプロパティからColumnsのコレクションを開き、列の編集画面で、ColumnTypeがDataGridViewTextBoxCellになっていると思いますが、これをmyDataGridViewTextBoxCellに変更できるようになっているはずですので、myDataGridViewTextBoxCellに変更して下さい。これで、この列のセルは、-を入力すると100が入るようになります。
もし、DataGridViewのデザイン画面で列の定義をされておらず、コードで定義されているのでしたら、
DataGridViewTextBoxCell myCell = new DataGridViewTextBoxCell();
を
myDataGridViewTextBoxCell myCell = new myDataGridViewTextBoxCell();
と変更するだけでOKです。
いろいろと書きましたが、うまく伝わりましたでしょうか?
オーバーライドとは、あるクラスの一部だけを変えたい場合に、そのクラスを継承したクラスで、変えたい部分だけを定義してあげたものと考えればわかりやすいのではないでしょうか? 継承したクラスにおいて、定義しない部分は、継承元のクラスのものが使われます。 変えたい部分だけを定義することによって、簡単にその部分だけ違う振る舞いをするクラスを作成できるという、実によくできているとは思いませんか? -
Ahf さんからの引用 質問1についてなのですが、これは編集中のセルの値、の場合でしょうか?それとも編集中に限らない話なのでしょうか?
編集中です。編集中でなければ何の問題もありません。
[quote user="trapemiya]いろいろと書きましたが、うまく伝わりましたでしょうか?
こんなに丁寧にしかもわかりやすくオーバーライドの有用性を教えてくださりありがとうございます。解説書を読んでいても今ひとつピンとこなかったことが,必要に迫られてみてtrapemiyaさんの解説のお陰もあって,便利なものだなあと実感しています。本当にありがとうございました。