之前介绍的使得PDA datagrid 能够进行编辑的实现方法:利用一个隐藏的textbox控件,当用户点击datagrid单元格变化引发事件CurrentCellChanged发生,在该事件中设置textbox可见,且显示信息即为当前选中的单元格的文本,当修改文本信息焦点离开textbox时,将textbox中的内容写入datagrid绑定的datatable中,这样就实现利用一个覆盖在单元格上的可编辑的textbox使得datagrid可编辑的功能。
但是它存在一个问题:当移动DataGrid的滚动条时,textbox仍在原来的位置,没有失去焦点。要解决这个问题,就需要能够捕捉到datagrid的拖动滚动条事件。
- 由于滚动条是当内容显示不够时,自动由datagrid提供的,观察发现在datagrid的相应事件里没有关于滚动条的事件。
- 考虑到滚动条移动,可能会导致paint事件,但是实践发现,DataGrid的滚动条操作,并没有引发paint事件(可能是因为滚动条滚动过程只是将本来已经画好的窗体挪过来,因为移动设备的屏幕很小,显示有限,它不是一个边画边更新的过程)。同样的道理,实验利用Form的Paint事件同样没有响应。
- 然后考虑用mousedown事件,捕捉鼠标点击位置坐标,但是发现鼠标移动到滚动条后就不返回点击位置坐标了。
- 综上考虑,如果想从DataGrid的事件中找到关于滚动条移动的事件不太可能,那我们是否可以获得datagrid中的滚动条对象呢??
查资料后发现,原来Datagrid控件是由三个控件组成,这些控件可以利用DataGrid.controls属性获得,利用DataGrid.controls.count可以获得控件的个数。
那么就可以按照DataGrid.controls[i]用i下标来访问每一个控件。
通过编程测试找到
DataGrid.controls[0]对应的是水平滚动条HScroll
DataGrid.controls[1]对应的是垂直滚动条VScroll
HScrollBar hScrollBar =
null;
VScrollBar vScrollBar = null;
// 绑定DataGrid滚动事件
private void BindScrollEvent()
{
foreach (Control c in this.Controls)
{
if (c is HScrollBar) hScrollBar = (HScrollBar)c;
if (c is VScrollBar) vScrollBar = (VScrollBar)c;
}
if (hScrollBar != null)
{
hScrollBar.ValueChanged -= new EventHandler(DataGrid_HScrollEvent);
hScrollBar.ValueChanged += new EventHandler(DataGrid_HScrollEvent);
}
if (vScrollBar != null)
{
vScrollBar.ValueChanged -= new EventHandler(DataGrid_VScrollEvent);
vScrollBar.ValueChanged += new EventHandler(DataGrid_VScrollEvent);
}
}
VScrollBar vScrollBar = null;
// 绑定DataGrid滚动事件
private void BindScrollEvent()
{
foreach (Control c in this.Controls)
{
if (c is HScrollBar) hScrollBar = (HScrollBar)c;
if (c is VScrollBar) vScrollBar = (VScrollBar)c;
}
if (hScrollBar != null)
{
hScrollBar.ValueChanged -= new EventHandler(DataGrid_HScrollEvent);
hScrollBar.ValueChanged += new EventHandler(DataGrid_HScrollEvent);
}
if (vScrollBar != null)
{
vScrollBar.ValueChanged -= new EventHandler(DataGrid_VScrollEvent);
vScrollBar.ValueChanged += new EventHandler(DataGrid_VScrollEvent);
}
}
因此我们可以针对水平滚动条,自己编写事件触发过程:
//
水平滚动事件
private void DataGrid_HScrollEvent( object sender, EventArgs e)
{
if (txtedit.Focus())
{
txtedit.Visible = false;
}
}
// 垂直滚动事件
private void DataGrid_VScrollEvent( object sender, EventArgs e)
{
if (txtedit.Focus())
{
txtedit.Visible = false;
}
}
private void DataGrid_HScrollEvent( object sender, EventArgs e)
{
if (txtedit.Focus())
{
txtedit.Visible = false;
}
}
// 垂直滚动事件
private void DataGrid_VScrollEvent( object sender, EventArgs e)
{
if (txtedit.Focus())
{
txtedit.Visible = false;
}
}
这样就实现了当点击datagrid的滚动条时让textbox失去焦点。
完整代码
using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections;
using System.Data;
namespace SmartDeviceProject1
{
public class datagridEx :DataGrid,ISupportInitialize
{
DataGridCell editcell = new DataGridCell();
Rectangle cellpos = new Rectangle();
TextBox txtedit = null;
HScrollBar hScrollBar = null;
VScrollBar vScrollBar = null;
bool isUpdateMode = false;
bool isEditMode = false;
public datagridEx()
{
InitTextBox();
BindScrollEvent();
}
/// <summary>
/// 初始化可编辑TextBox
/// </summary>
private void InitTextBox()
{
txtedit = new TextBox();
this.Controls.Add(txtedit);
txtedit.Visible = false;
txtedit.BringToFront();
txtedit.Text = " grn ";
txtedit.KeyPress -= new KeyPressEventHandler(txedit_KeyPress);
txtedit.KeyPress += new KeyPressEventHandler(txedit_KeyPress);
}
// 绑定DataGrid滚动事件
private void BindScrollEvent()
{
foreach (Control c in this.Controls)
{
if (c is HScrollBar) hScrollBar = (HScrollBar)c;
if (c is VScrollBar) vScrollBar = (VScrollBar)c;
}
if (hScrollBar != null)
{
hScrollBar.ValueChanged -= new EventHandler(DataGrid_HScrollEvent);
hScrollBar.ValueChanged += new EventHandler(DataGrid_HScrollEvent);
}
if (vScrollBar != null)
{
vScrollBar.ValueChanged -= new EventHandler(DataGrid_VScrollEvent);
vScrollBar.ValueChanged += new EventHandler(DataGrid_VScrollEvent);
}
}
DataGridCell currentcell;
protected override void OnCurrentCellChanged(EventArgs e)
{
if (isUpdateMode)
{
base.OnCurrentCellChanged(e);
return;
}
currentcell = this.CurrentCell;
if (isEditMode && ! this.CurrentCell.Equals(editcell))
{
isUpdateMode = true;
this[editcell.RowNumber, editcell.ColumnNumber] = txtedit.Text;
this.CurrentCell = currentcell;
this.Visible = true;
txtedit.Visible = false;
isUpdateMode = false;
isEditMode = false;
}
editcell = this.CurrentCell;
cellpos = this.GetCellBounds(editcell.RowNumber, editcell.ColumnNumber);
txtedit.Left = cellpos.Left - 1;
txtedit.Top = cellpos.Top - 1;
txtedit.Width = cellpos.Width + 2;
txtedit.Height = cellpos.Height + 2;
txtedit.Visible = true;
txtedit.Text = this[editcell.RowNumber, editcell.ColumnNumber].ToString();
txtedit.BringToFront();
txtedit.Focus();
txtedit.SelectAll();
isEditMode = true;
base.OnCurrentCellChanged(e);
}
private void txedit_KeyPress( object sender, KeyPressEventArgs e)
{
if (e.KeyChar == ( char)Keys.Enter)
{
txtedit.Visible = false;
this[currentcell.RowNumber, currentcell.ColumnNumber] = txtedit.Text;
this.Focus();
if (currentcell.RowNumber + 1 < this.VisibleRowCount)
currentcell.RowNumber = currentcell.RowNumber + 1;
this.CurrentCell = currentcell;
isUpdateMode = false;
isEditMode = true;
}
}
// 水平滚动事件
private void DataGrid_HScrollEvent( object sender, EventArgs e)
{
if (txtedit.Focus())
{
txtedit.Visible = false;
}
}
// 垂直滚动事件
private void DataGrid_VScrollEvent( object sender, EventArgs e)
{
if (txtedit.Focus())
{
txtedit.Visible = false;
}
}
#region ISupportInitialize接口实现
public void BeginInit()
{
}
public void EndInit()
{
}
#endregion
}
}
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections;
using System.Data;
namespace SmartDeviceProject1
{
public class datagridEx :DataGrid,ISupportInitialize
{
DataGridCell editcell = new DataGridCell();
Rectangle cellpos = new Rectangle();
TextBox txtedit = null;
HScrollBar hScrollBar = null;
VScrollBar vScrollBar = null;
bool isUpdateMode = false;
bool isEditMode = false;
public datagridEx()
{
InitTextBox();
BindScrollEvent();
}
/// <summary>
/// 初始化可编辑TextBox
/// </summary>
private void InitTextBox()
{
txtedit = new TextBox();
this.Controls.Add(txtedit);
txtedit.Visible = false;
txtedit.BringToFront();
txtedit.Text = " grn ";
txtedit.KeyPress -= new KeyPressEventHandler(txedit_KeyPress);
txtedit.KeyPress += new KeyPressEventHandler(txedit_KeyPress);
}
// 绑定DataGrid滚动事件
private void BindScrollEvent()
{
foreach (Control c in this.Controls)
{
if (c is HScrollBar) hScrollBar = (HScrollBar)c;
if (c is VScrollBar) vScrollBar = (VScrollBar)c;
}
if (hScrollBar != null)
{
hScrollBar.ValueChanged -= new EventHandler(DataGrid_HScrollEvent);
hScrollBar.ValueChanged += new EventHandler(DataGrid_HScrollEvent);
}
if (vScrollBar != null)
{
vScrollBar.ValueChanged -= new EventHandler(DataGrid_VScrollEvent);
vScrollBar.ValueChanged += new EventHandler(DataGrid_VScrollEvent);
}
}
DataGridCell currentcell;
protected override void OnCurrentCellChanged(EventArgs e)
{
if (isUpdateMode)
{
base.OnCurrentCellChanged(e);
return;
}
currentcell = this.CurrentCell;
if (isEditMode && ! this.CurrentCell.Equals(editcell))
{
isUpdateMode = true;
this[editcell.RowNumber, editcell.ColumnNumber] = txtedit.Text;
this.CurrentCell = currentcell;
this.Visible = true;
txtedit.Visible = false;
isUpdateMode = false;
isEditMode = false;
}
editcell = this.CurrentCell;
cellpos = this.GetCellBounds(editcell.RowNumber, editcell.ColumnNumber);
txtedit.Left = cellpos.Left - 1;
txtedit.Top = cellpos.Top - 1;
txtedit.Width = cellpos.Width + 2;
txtedit.Height = cellpos.Height + 2;
txtedit.Visible = true;
txtedit.Text = this[editcell.RowNumber, editcell.ColumnNumber].ToString();
txtedit.BringToFront();
txtedit.Focus();
txtedit.SelectAll();
isEditMode = true;
base.OnCurrentCellChanged(e);
}
private void txedit_KeyPress( object sender, KeyPressEventArgs e)
{
if (e.KeyChar == ( char)Keys.Enter)
{
txtedit.Visible = false;
this[currentcell.RowNumber, currentcell.ColumnNumber] = txtedit.Text;
this.Focus();
if (currentcell.RowNumber + 1 < this.VisibleRowCount)
currentcell.RowNumber = currentcell.RowNumber + 1;
this.CurrentCell = currentcell;
isUpdateMode = false;
isEditMode = true;
}
}
// 水平滚动事件
private void DataGrid_HScrollEvent( object sender, EventArgs e)
{
if (txtedit.Focus())
{
txtedit.Visible = false;
}
}
// 垂直滚动事件
private void DataGrid_VScrollEvent( object sender, EventArgs e)
{
if (txtedit.Focus())
{
txtedit.Visible = false;
}
}
#region ISupportInitialize接口实现
public void BeginInit()
{
}
public void EndInit()
{
}
#endregion
}
}