【原创】PDA DataGrid的滚动条事件处理

时间:2021-01-02 16:22:47

之前介绍的使得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);
            }
        }

 

因此我们可以针对水平滚动条,自己编写事件触发过程:

 

// 水平滚动事件
         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

    }   
}