私はDataGridViews
でプログラムに取り組んでいます。 1つのDatagridView
にはDataGridViewTextBoxColumn
があり、これはユーザーが編集できるようになっています。ユーザーが数字の入力を終えたら、キーボードのEnterキーを押します。これで、DataGridView
はすべてのEvents
を実行し、結局のところEvents
、最後に問題が発生します。
すべてが完了し、Windowsは次のDataGridViewRow
を選択する予定ですが、これを防ぐことはできません。
私は試した
_if (e.KeyData == Keys.Enter) e.SuppressKeyPress = true; // or e.Handled
_
私が見つけたほぼすべてのイベントで。残念ながら、DataGridViewTextBoxColumn
が編集モードでない場合にのみ、ENTERキーを防ぐことができました。
編集中にENTERを見つける方法は次のとおりです
イベントの追加
_private void dgr_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
e.Control.KeyPress += new KeyPressEventHandler(dgr_KeyPress_NumericTester);
}
_
そして、これは数値入力のみを受け入れるイベントです。
_private void dgr_KeyPress_NumericTester(object sender, KeyPressEventArgs e)
{
if (!Char.IsDigit(e.KeyChar) && e.KeyChar != 8) e.Handled = true;
}
_
詳細に説明するには:
ユーザーがいくつかの依存関係がある値を入力すると、別のコントロールにフォーカスを与えたいので、彼は依存関係を修正するために使用されます。
DependingControl.Focus()
でも試してみましたが、最後の「enter」がビューの最後になります。
誰かがこれを防ぐ方法を知っていますか?
さて、私はあなたが望むことをする何かをうまく動かすことができました(または少なくとも難しい部分はあなたがすでに他のほとんどのことをしたと思います)が、解決策は私の肌を這わせます。
セルを編集するときに、CellEndEdit
イベントとSelectionChanged
イベントを組み合わせて使用するように、Enterキーイベントを「キャンセル」することになりました。
いくつかの状態を格納するクラスレベルのフィールドをいくつか紹介しました。特に、セルの編集の最後にある行と、選択を停止するかどうかを変更しました。
コードは次のようになります。
public partial class Form1 : Form
{
private int currentRow;
private bool resetRow = false;
public Form1()
{
InitializeComponent();
// deleted out all the binding code of the grid to focus on the interesting stuff
dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEndEdit);
// Use the DataBindingComplete event to attack the SelectionChanged,
// avoiding infinite loops and other nastiness.
dataGridView1.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(dataGridView1_DataBindingComplete);
}
void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (resetRow)
{
resetRow = false;
dataGridView1.CurrentCell = dataGridView1.Rows[currentRow].Cells[0];
}
}
void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
resetRow = true;
currentRow = e.RowIndex;
}
void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
dataGridView1.SelectionChanged += new EventHandler(dataGridView1_SelectionChanged);
}
}
これを徹底的にテストして、必要なことを正確に実行できることを確認する必要があります。編集コントロールのEnterキーを押したときに、行の変更が停止することを確認しただけです。
私が言ったように-私はこのようなことをする必要があることにあまり満足していません-それはかなりもろく感じます、そしてまたそれは奇妙な副作用を持っているかもしれないようです。しかし、あなたがこの振る舞いをしなければならず、あなたがそれをうまくテストするなら、これがあなたが望むことをする唯一の方法だと思います。
テキストボックス列からカスタム列を継承し、以下のイベントをオーバーライドすることで、グリッドのEnter動作を変更するためにこれを試しました
protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == Keys.Enter)
return base.ProcessDialogKey(Keys.Tab);
else
return base.ProcessDialogKey(keyData);
}
したがって、Enterキーが送信される代わりに、次のセルに移動するTabのアクションをエミュレートします。お役に立てれば
Private Sub DataGridView1_KeyDown(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyDown
If e.KeyData = Keys.Enter Then e.Handled = True
End Sub
これは単なる回避策であり、実際の解決策ではありませんが、機能します。
この質問はずっと前から行われていたことは知っていますが、将来検索する人にとっては役立つかもしれません。最善の解決策は、カスタム列を使用することです。テキストボックスの場合は、組み込みのクラスを利用するため、簡単です。
class Native
{
public const uint WM_KEYDOWN = 0x100;
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
}
//the column that will be added to dgv
public class CustomTextBoxColumn : DataGridViewColumn
{
public CustomTextBoxColumn() : base(new CustomTextCell()) { }
public override DataGridViewCell CellTemplate
{
get { return base.CellTemplate; }
set
{
if (value != null && !value.GetType().IsAssignableFrom(typeof(CustomTextCell)))
{
throw new InvalidCastException("Must be a CustomTextCell");
}
base.CellTemplate = value;
}
}
}
//the cell used in the previous column
public class CustomTextCell : DataGridViewTextBoxCell
{
public override Type EditType
{
get { return typeof(CustomTextBoxEditingControl); }
}
}
//the edit control that will take data from user
public class CustomTextBoxEditingControl : DataGridViewTextBoxEditingControl
{
protected override void WndProc(ref Message m)
{
//we need to handle the keydown event
if (m.Msg == Native.WM_KEYDOWN)
{
if((ModifierKeys&Keys.Shift)==0)//make sure that user isn't entering new line in case of warping is set to true
{
Keys key=(Keys)m.WParam;
if (key == Keys.Enter)
{
if (this.EditingControlDataGridView != null)
{
if(this.EditingControlDataGridView.IsHandleCreated)
{
//sent message to parent dvg
Native.PostMessage(this.EditingControlDataGridView.Handle, (uint)m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32());
m.Result = IntPtr.Zero;
}
return;
}
}
}
}
base.WndProc(ref m);
}
}
次に、dgv自体に移動し、DataGridViewから派生した新しいクラスを使用して列を追加し、wndprocからのEnterキーも処理しました。
void Initialize()
{
CustomTextBoxColumn colText = new CustomTextBoxColumn();
colText.DataPropertyName = colText.Name = columnTextName;
colText.HeaderText = columnTextAlias;
colText.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
this.Columns.Add(colText);
DataGridViewTextBoxColumn colText2 = new DataGridViewTextBoxColumn();
colText2.DataPropertyName = colText2.Name = columnText2Name;
colText2.HeaderText = columnText2Alias;
colText2.DefaultCellStyle.WrapMode = DataGridViewTriState.False;
this.Columns.Add(colText2);
}
protected override void WndProc(ref Message m)
{
//the enter key is sent by edit control
if (m.Msg == Native.WM_KEYDOWN)
{
if ((ModifierKeys & Keys.Shift) == 0)
{
Keys key = (Keys)m.WParam;
if (key == Keys.Enter)
{
MoveToNextCell();
m.Result = IntPtr.Zero;
return;
}
}
}
base.WndProc(ref m);
}
//move the focus to the next cell in same row or to the first cell in next row then begin editing
public void MoveToNextCell()
{
int CurrentColumn, CurrentRow;
CurrentColumn = this.CurrentCell.ColumnIndex;
CurrentRow = this.CurrentCell.RowIndex;
if (CurrentColumn == this.Columns.Count - 1 && CurrentRow != this.Rows.Count - 1)
{
this.CurrentCell = Rows[CurrentRow + 1].Cells[1];//0 index is for No and readonly
this.BeginEdit(false);
}
else if(CurrentRow != this.Rows.Count - 1)
{
base.ProcessDataGridViewKey(new KeyEventArgs(Keys.Tab));
this.BeginEdit(false);
}
}
この答えは本当に遅れます...
しかし、私はまったく同じ問題を抱えていて、行などをキャッシュしたくありませんでした。それで私はグーグルで回りました、そしてこれは質問に対する私の解決策です。クレジット Enterキーを押してもDataGridViewでEditModeが終了しないようにするにはどうすればよいですか?
DataGridViewから継承し、次のコード(vb.net)を追加します。
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If Commons.Options.RowWiseNavigation AndAlso Me.IsCurrentCellInEditMode AndAlso (keyData = Keys.Enter Or keyData = Keys.Tab) Then
' End EditMode, then raise event, so the standard-handler can run and the refocus is being done
Me.EndEdit()
OnKeyDown(New KeyEventArgs(keyData))
Return True
End If
'Default
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
簡単にできます...
1 ...そのグリッドビューのKeyDownイベントを作成します(グリッドビューのプロパティに移動し、KeyDownイベントをダブルクリックします)。
2 ...このコードを貼り付けます-
if(e.KeyData == Keys.Enter)
{
e.Handled = true;
}
3 ...ついにこんな感じ。
private void dgvSearchResults_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Enter)
{
e.Handled = true;
}
}
4 ..プログラムを実行してを参照してください。
単にそれが大丈夫になることをしてください。
private void dataGridViewX1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
SendKeys.Send("{UP}");
SendKeys.Send("{Right}");
}