トップ回答者
DataGridViewコントロールの入力可能文字の制御について

質問
-
DataGridViewコントロールで、入力できる文字種(「数字のみ」「英字のみ」等)の
制御をしたいと思い、次のページの例を参考に試してみたのですが、
今一つ正しく機能しません。
数字または一部の文字しか入力できないようにする
http://jeanne.wankuma.com/tips/textbox/permitchars.html
overrideしたWndProc()で、Windowsメッセージ(キー入力)を捕える事ができない
のです。
DataGridView.EditModeプロパティの値を「EditOnKeystrokeOrF2」の場合、
初めに入力したキーのみ捕える事ができるのですが、それ以降は捕える事が
できません。
EditModeプロパティの値を「EditOnEnter」の場合、一切捕える事ができません。
皆様、ご教授願えますでしょうか。
環境:
Windows Vista Ultimate
Visual Studio 2005 Professional Edition SP1
.NET Framework 2.0
回答
-
このページをみてください。
http://mnow.wankuma.com/cs2005_datagridview_control5.html
DataGridViewコントロールのTextBox(DataGridViewTextBoxColumn)を拡張して、
自分の機能を実装するにはDataGridViewColumn や DataGridViewCell を継承してプロパティや動作を拡張する
ことが必要ですが、今回はIDataGridViewEditingControl から派生し、Control を実装するクラスを拡張するだけですので、
以下のあたりを実装すればいいと思いますよ。
public class MyTextBoxColumn : DataGridViewTextBoxColumn
public MyTextBoxColumn()
public override DataGridViewCell CellTemplate
public class MyTextBoxCell : DataGridViewTextBoxCell
public override void InitializeEditingControl
public override Type EditType
class MyTextBoxEditingControl : DataGridViewTextBoxEditingControl
-
結局簡易版のEditingControlWantsInputKeyは以下のコードでよさそうですね。
(正しいEditingControlWantsInputKeyは各キーの有効条件も加味したほうがいいです。)
DataGridViewTextBoxEditingControl.EditingControlWantsInputKey メソッドのHELPの以下の文章を読む限りですが、
戻り値は false じゃなくて !dataGridViewWantsInputKey が正しそうです。
dataGridViewWantsInputKey
DataGridView が keyData の処理を必要とする場合は true。それ以外の場合は false。戻り値
指定されたキーが編集コントロールによって処理される通常の入力キーの場合は true。それ以外の場合は false。Code Snippetpublic bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
{
switch ((keyData & Keys.KeyCode))
{
case Keys.Prior:
case Keys.Next:
case Keys.End:
case Keys.Home:
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
case Keys.Delete:
case Keys.Return:
return true;
}
return !dataGridViewWantsInputKey;
}
すべての返信
-
このページをみてください。
http://mnow.wankuma.com/cs2005_datagridview_control5.html
DataGridViewコントロールのTextBox(DataGridViewTextBoxColumn)を拡張して、
自分の機能を実装するにはDataGridViewColumn や DataGridViewCell を継承してプロパティや動作を拡張する
ことが必要ですが、今回はIDataGridViewEditingControl から派生し、Control を実装するクラスを拡張するだけですので、
以下のあたりを実装すればいいと思いますよ。
public class MyTextBoxColumn : DataGridViewTextBoxColumn
public MyTextBoxColumn()
public override DataGridViewCell CellTemplate
public class MyTextBoxCell : DataGridViewTextBoxCell
public override void InitializeEditingControl
public override Type EditType
class MyTextBoxEditingControl : DataGridViewTextBoxEditingControl
-
じゃんぬねっとさん、えムナウさん、いつもありがとうございます。
返信遅れましたが、大変参考になりました。
ありがとうございます。
追伸
私自身、次のスレッドも参考にしたので、今後、このスレッドを見る方の
参考になればと思い、アンカーを残しておきます。
DataGridViewTextBoxColumnの追加プロパティの保存方法について
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=999510&SiteID=7
スレッドのタイトルから、質問自体の内容は直接関係ないですが、スレッドに
載っていたソースが参考になったので。
-
一旦、解決済みにしたんですが、もう一度質問させてください。
DataGridViewTextBoxColumnの追加プロパティの保存方法について
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=999510&SiteID=7
このスレッドのソースを元に、「DataGridViewTextBoxColumn」を継承させてみた
のですが、ピリオド「.」だけが入力できなくて困っています。
DataGridViewTextBoxColumnでは問題なく入力できるので、継承した事によって(?)
何らかの制限が効いている状態になっているんだとは思うのですが、それが何なのか
よく分からなくて。
ちなみに、ペースト(貼り付け)だと問題なく入力(貼り付け)できます。
キーボードからの入力ができないのです。
ご教授願えますでしょうか。
長くなりますが、ソースをUPします。
//MyTextBoxコントロール
public class MyTextBoxEditingControl : TextBox, IDataGridViewEditingControl
{
private DataGridView dataGridViewControl;
private bool valueIsChanged = false;
private int rowIndexNum;public object EditingControlFormattedValue {
get { return this.Text; }
set {
if (value is string)
{
this.Text = value.ToString();
}
}
}public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
{return this.Text;
}public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
{this.Font = dataGridViewCellStyle.Font;
this.ForeColor = dataGridViewCellStyle.ForeColor;
this.BackColor = dataGridViewCellStyle.BackColor;
this.TextAlign = translateAlignment(dataGridViewCellStyle.Alignment);MyTextBoxCell cell = EditingControlDataGridView.CurrentCell as MyTextBoxCell;
MyTextBoxColumn col = cell.OwningColumn as MyTextBoxColumn;
this.MaxLength = col.MaxInputLength;
}public int EditingControlRowIndex {
get { return rowIndexNum; }
set { rowIndexNum = value; }
}
public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
{switch (key & Keys.KeyCode) {
case Keys.Left:
case Keys.Up:
case Keys.Down:
case Keys.Right:
case Keys.Home:
case Keys.End:
case Keys.PageDown:
case Keys.PageUp:return true;
default:
return false;
}}
public void PrepareEditingControlForEdit(bool selectAll)
{if (selectAll)
{
this.SelectAll();
}
}public bool RepositionEditingControlOnValueChange {
get { return false; }
}
public DataGridView EditingControlDataGridView {get { return dataGridViewControl; }
set { dataGridViewControl = value; }
}
public bool EditingControlValueChanged {get { return valueIsChanged; }
set { valueIsChanged = value; }
}
public Cursor EditingPanelCursor {get { return base.Cursor; }
}
protected override void OnTextChanged(System.EventArgs e)
{
valueIsChanged = true;
if (dataGridViewControl != null)
{
dataGridViewControl.NotifyCurrentCellDirty(true);
}
base.OnTextChanged(e);
}private static HorizontalAlignment translateAlignment(DataGridViewContentAlignment align)
{
switch (align) {
case DataGridViewContentAlignment.TopLeft:
case DataGridViewContentAlignment.MiddleLeft:
case DataGridViewContentAlignment.BottomLeft:
return HorizontalAlignment.Left;case DataGridViewContentAlignment.TopCenter:
case DataGridViewContentAlignment.MiddleCenter:
case DataGridViewContentAlignment.BottomCenter:
return HorizontalAlignment.Center;case DataGridViewContentAlignment.TopRight:
case DataGridViewContentAlignment.MiddleRight:
case DataGridViewContentAlignment.BottomRight:
return HorizontalAlignment.Right;
}return HorizontalAlignment.Left;
}
}
//MyTextBoxCellクラスpublic class MyTextBoxCell : DataGridViewTextBoxCell
{public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
MyTextBoxEditingControl ctl = (MyTextBoxEditingControl)DataGridView.EditingControl;
ctl.Text = (string)this.Value;
ctl.MaxLength = this.MaxInputLength;}
public override Type EditType {
get { return typeof(MyTextBoxEditingControl); }
}public override Type ValueType {
get { return typeof(string); }
}
public override object Clone()
{
MyTextBoxCell cloneObj = base.Clone() as MyTextBoxCell;
cloneObj.MaxInputLength = this.MaxInputLength;
return cloneObj;
}}
//MyTextBoxColumnクラス
public class MyTextBoxColumn : DataGridViewTextBoxColumn
{public MyTextBoxColumn() : base()
{
base.CellTemplate = new MyTextBoxCell();
}public override DataGridViewCell CellTemplate {
get { return base.CellTemplate; }
set { base.CellTemplate = value; }
}
public override object Clone()
{
MyTextBoxColumn cloneObj = base.Clone() as MyTextBoxColumn;
cloneObj.MaxInputLength = this.MaxInputLength;
return cloneObj;
}
} -
「MyTextBoxEditingControl.EditingControlWantsInputKey」に次の処理を追加
したら入力できる様になったのですが。。。
case Keys.Decimal:
case Keys.OemPeriod:
return true;「指定されたキーが編集コントロールによって処理される通常の入力キーの場合は true。それ以外の場合は false。」
(IDataGridViewEditingControl.EditingControlWantsInputKey メソッド
)より
この事より、「true」を返す、というのは何となく正しい対応の様な気がするんですが、
では、逆に、カンマ「,」やプラス「+」、アットマーク「@」等々は、何故にコーディング
しなくても入力できるのでしょうか?
今一つ、EditingControlWantsInputKeyメソッドの使い方がよく分らないのですが。
皆様、ご教授願えますでしょうか。
-
EditingControlWantsInputKey の元々のパタメータ値を無視しているのがなんともなんですが。
元々のdataGridViewWantsInputKeyも以下の場合がTrueですのでいい気もします。
Keys.Escape
Keys.Space
Keys.Prior
Keys.Next
Keys.End
Keys.Home
Keys.Left
Keys.Up
Keys.Right
Keys.Down
Keys.Delete
Keys.F2
Keys.Tab
Keys.ReturnDataGridViewTextBoxEditingControlを継承しなかったのは単に参考にしたソースが、
そうしていたからでしょうか?
提示のサイトも元情報は以下のサイトだと思います。
http://msdn2.microsoft.com/ja-jp/library/7tas5c80(VS.80).aspx
EditingControlWantsInputKey 自体はDataGridView.ProcessKeyPreview メソッドで使って、
そのキーのイベントをコントロールが処理したことを示します。
この場合は他のコントロールにイベントが渡らないことになります。
UserControlやFormがほかのコントロールでしょうからKeys.Decimal、Keys.OemPeriodでも問題は発生しません。
通常はUserControlやFormがキーに反応して何かやっていない限りはこんなことは起こらないはずなんですけどね。
-
えムナウさん、いつも本当にありがとうございます。
>EditingControlWantsInputKey の元々のパタメータ値を無視しているのがなんともなんですが
どういう事でしょうか?
本来なら、
Keys.Escape~Keys.Return全て、コーディングしておくべきもの、という事でしょうか?
>提示のサイトも元情報は以下のサイトだと思います。
>http://msdn2.microsoft.com/ja-jp/library/7tas5c80(VS.80).aspx
はい、多分そうだと思います。
>DataGridViewTextBoxColumnの追加プロパティの保存方法について
>http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=999510&SiteID=7
には、VBのコードだけだったので、元情報と思われるページのC#のソースも参考にしながら、
コーディングしました。
>DataGridViewTextBoxEditingControlを継承しなかったのは単に参考にしたソースが、
>そうしていたからでしょうか?
最終的には、次のページに載っているカスタムコントロールを継承するつもりでおります。
数字または一部の文字しか入力できないようにする
http://jeanne.wankuma.com/tips/textbox/permitchars.html
public class MyTextBox : System.Windows.Forms.TextBox
{
}
public class MyTextBoxEditingControl : MyTextBox, IDataGridViewEditingControl
{
}
こんな感じになるかと考えています。
それで、まずはファーストステップとして、参考にしたコードの通り、単純にTextBoxを継承してみた
のです。
>通常はUserControlやFormがキーに反応して何かやっていない限りはこんなことは起こらないはず
つまり、どういう事でしょうか?
プロジェクトには、Formと、DataGridViewから継承したカスタムコントロールしかありません。
コーディングしたのは、先にUPしたカスタムコントロールに施したコードのみです。
Formには何もコーディングしていません。
にも関わらず、ピリオド「.」が入力できないのは、摩訶不思議な事が起きている、という事でしょうか?
-
ぶるーの さんからの引用 >EditingControlWantsInputKey の元々のパタメータ値を無視しているのがなんともなんですが
どういう事でしょうか?
本来なら、
Keys.Escape~Keys.Return全て、コーディングしておくべきもの、という事でしょうか?
dataGridViewWantsInputKeyパラメータを無視しているという意味ですが、
Microsoftのサンプルもそうなのでまぁいいかなと。
ぶるーの さんからの引用 >DataGridViewTextBoxEditingControlを継承しなかったのは単に参考にしたソースが、
>そうしていたからでしょうか?
最終的には、次のページに載っているカスタムコントロールを継承するつもりでおります。
数字または一部の文字しか入力できないようにする
http://jeanne.wankuma.com/tips/textbox/permitchars.html
public class MyTextBox : System.Windows.Forms.TextBox
{
}
public class MyTextBoxEditingControl : MyTextBox, IDataGridViewEditingControl
{
}
こんな感じになるかと考えています。
それで、まずはファーストステップとして、参考にしたコードの通り、単純にTextBoxを継承してみた
のです。
了解です。
ぶるーの さんからの引用 >通常はUserControlやFormがキーに反応して何かやっていない限りはこんなことは起こらないはず
つまり、どういう事でしょうか?
プロジェクトには、Formと、DataGridViewから継承したカスタムコントロールしかありません。
コーディングしたのは、先にUPしたカスタムコントロールに施したコードのみです。
Formには何もコーディングしていません。
にも関わらず、ピリオド「.」が入力できないのは、摩訶不思議な事が起きている、という事でしょうか?
ちょっと再現試験していないのでわからないですが、不思議な状況ですね。
-
結局簡易版のEditingControlWantsInputKeyは以下のコードでよさそうですね。
(正しいEditingControlWantsInputKeyは各キーの有効条件も加味したほうがいいです。)
DataGridViewTextBoxEditingControl.EditingControlWantsInputKey メソッドのHELPの以下の文章を読む限りですが、
戻り値は false じゃなくて !dataGridViewWantsInputKey が正しそうです。
dataGridViewWantsInputKey
DataGridView が keyData の処理を必要とする場合は true。それ以外の場合は false。戻り値
指定されたキーが編集コントロールによって処理される通常の入力キーの場合は true。それ以外の場合は false。Code Snippetpublic bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
{
switch ((keyData & Keys.KeyCode))
{
case Keys.Prior:
case Keys.Next:
case Keys.End:
case Keys.Home:
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
case Keys.Delete:
case Keys.Return:
return true;
}
return !dataGridViewWantsInputKey;
} -
えムナウさん、回答ありがとうございます。
期待通りの結果が得られる様になりました。
>EditingControlWantsInputKey メソッドのHELPの以下の文章を読む限り
ヘルプは読んでたつもりだったんですが、「dataGridViewWantsInputKey」の扱い方を
理解していなかったみたいです。
ソースを提示して頂いて、改めてそういう風に使うのか、と理解しました(汗)
何にせよ、マルっと解決できました。
ありがとうございました。
追伸:
再質問する際、「ピリオドだけが入力できない」と書きましたが、ピリオド「.」以外に
「q!"#$%&'()」も入力できない事が分りました。
ただ今回、えムナウさんが提示して頂いたソースで、全て解決できました。