一.引子
當我們在做WinForm的數據庫開發時,時常會用到datagridvIEw控件來顯示數據.在提供數據交互的時候,常常希望可以對用戶輸入的數據進行校驗.對於一些類似金額的字段,要求只允許輸入數字,並且要控制精度.這個時候,我們通常會想到2種解決方法.其一,就是先任隨用戶輸入,然後在Invalidating或lostfocus等事件中做驗證並提示.其二,就是我這裡所演示的方法,就是直接控制用戶的輸入,這樣將省略去很多冗繁的操作,給數據庫程序的快速開發帶來方便.
二.設計時效果

三.運行時效果

四.源代碼
1)DataGridVIEwTextBoxCell

using System;

using System.Collections.Generic;

using System.Text;

using System.Windows.Forms;

using System.ComponentModel;


namespace JcsExpLibary.Numeric_Textbox


...{

public class JcsNumTextBoxCell : DataGridVIEwTextBoxCell


...{

private bool _isreadonly = true; //是否允許回車代替TAB

private bool _isintegral = false;//是否整數輸入

private bool _EnPaste = true;//是否允許粘貼

private bool _EnContextMenu = true; //是否允許現實右鍵菜單

private int _PointNumber = -1;//為-1時允許輸入任意位小數

private bool _isnegativenumber = false; //是否允許輸入負數



public JcsNumTextBoxCell(): base()


...{

}


/**//// <summary>

/// 是否只讀

/// </summary>

[Category("JCS屬性"), Description("是否只讀。")]

public bool Isreadonly


...{


get ...{ return this._isreadonly; }


set ...{ this._isreadonly = value; }

}


/**//// <summary>

/// 是否是整數

/// </summary>

[Category("JCS屬性"), Description("是否整數。")]

public bool isintegral


...{


get ...{ return this._isintegral; }


set ...{ _isintegral = value; }

}



/**//// <summary>

/// 是否允許輸入負數

/// </summary>

[Category("JCS屬性"), Description("是否允許輸入負數。")]

public bool IsNegativeNumber


...{

[Category("JCS屬性"), Description("是否整數。")]

public bool isintegral


...{


get ...{ return this._isintegral; }


set ...{ _isintegral = value; }

}



/**//// <summary>

/// 是否允許輸入負數

/// </summary>

[Category("JCS屬性"), Description("是否允許輸入負數。")]

public bool IsNegativeNumber


...{


get ...{ return _isnegativenumber; }


set ...{ _isnegativenumber = value; }

}


/**//// <summary>

/// 精度位數控制(即:允許輸入幾位小數控制)

/// </summary>

[Category("JCS屬性"), Description("精度位數控制,-1時允許輸入任意位小數。")]

public int PointNumber


...{


get ...{ return _PointNumber; }


set ...{ this._PointNumber = value; }

}

[Category("JCS屬性"), Description("是否允許粘貼。")]

public bool EnablePaste


...{


get ...{ return _EnPaste; }

set


...{

_EnPaste = value;

}

}


/**//// <summary>

///

/// </summary>

[Category("JCS屬性"), Description("是否右鍵菜單。")]

public bool EnableContextMenu


...{



get ...{ return _EnContextMenu; }

set


...{

_EnContextMenu = value;

}

}

//初始化用於編輯單元格的控件

public override void InitializeEditingControl(int rowIndex,

object initialFormattedValue,

DataGridViewCellStyle dataGridVIEwCellStyle)


...{

JcsNumTextBoxEditingControl numbertextbox;

JcsNumTextBoxColumn jcsnumcol;

DataGridVIEwColumn dgvc;


base.InitializeEditingControl(rowIndex, initialFormattedValue,

dataGridVIEwCellStyle);

//獲取承載控件

numbertextbox = DataGridVIEw.EditingControl as JcsNumTextBoxEditingControl;


//獲取包含此單元格的列

dgvc = this.OwningColumn; // this.DataGridVIEw.Columns[this.ColumnIndex];

if (dgvc is JcsNumTextBoxColumn)


...{

jcsnumcol = dgvc as JcsNumTextBoxColumn;

numbertextbox.Isreadonly = jcsnumcol.Isreadonly;

numbertextbox.isintegral = jcsnumcol.isintegral;

numbertextbox.IsNegativeNumber = jcsnumcol.IsNegativeNumber;

numbertextbox.PointNumber = jcsnumcol.PointNumber;

numbertextbox.EnablePaste = jcsnumcol.EnablePaste;

numbertextbox.EnableContextMenu = jcsnumcol.EnableContextMenu;

numbertextbox.Text = (string)this.Value;

}

}


//獲取單元格的寄宿編輯控件的類型

public override Type EditType


...{

get


...{

return typeof(JcsNumTextBoxEditingControl);

}

}

}

}
2)DataGridVIEwColumn

using System;

using System.Collections.Generic;

using System.Text;

using System.ComponentModel;

using System.Windows.Forms;

using System.Drawing;


namespace JcsExpLibary.Numeric_Textbox


...{

public class JcsNumTextBoxColumn : DataGridVIEwColumn


...{

private bool _isreadonly = true; //是否允許回車代替TAB

private bool _isintegral = false;//是否整數輸入

private bool _EnPaste = true;//是否允許粘貼

private bool _EnContextMenu = true; //是否允許現實右鍵菜單

private int _PointNumber = -1;//為-1時允許輸入任意位小數

private bool _isnegativenumber = false; //是否允許輸入負數



public JcsNumTextBoxColumn()

: base(new JcsNumTextBoxCell())


...{

}



/**//// <summary>

/// 是否只讀

/// </summary>

[Category("JCS屬性"), Description("是否只讀。")]

public bool Isreadonly


...{


get ...{ return this._isreadonly; }


set ...{ this._isreadonly = value; }

}


/**//// <summary>

/// 是否是整數

/// </summary>

[Category("JCS屬性"), Description("是否整數。")]

public bool isintegral


...{


get ...{ return this._isintegral; }

set


...{

if (this._isintegral != value)


...{

this._isintegral = value;

JcsNumTextBoxCell jcsnumcel;

DataGridVIEwCell dgvc;

int rowCount;

//

// first, update the value on the template cell.

//

jcsnumcel = (JcsNumTextBoxCell)this.CellTemplate;

jcsnumcel.isintegral = value;


//

// now set it on all cells in other rows as well.

//

if (this.DataGridView != null && this.DataGridVIEw.Rows != null)


...{

rowCount = this.DataGridVIEw.Rows.Count;

for (int i = 0; i < rowCount; i++)


...{

dgvc = this.DataGridVIEw.Rows.SharedRow(i).Cells[i];

if (dgvc is JcsNumTextBoxCell)


...{

jcsnumcel = (JcsNumTextBoxCell)dgvc;

jcsnumcel.isintegral = value;

}

}

}

}

}

}



/**////&;<summary>

/// 是否允許輸入負數

/// </summary>

[Category("JCS屬性"), Description("是否允許輸入負數。")]

public bool IsNegativeNumber


...{


get ...{ return _isnegativenumber; }


set ...{ _isnegativenumber = value; }

}


/**//// <summary>

/// 精度位數控制(即:允許輸入幾位小數控制)

/// </summary>

[Category("JCS屬性"), Description("精度位數控制,-1時允許輸入任意位小數。")]

public int PointNumber


...{


get ...{ return _PointNumber; }


set ...{ this._PointNumber = value; }

}

[Category("JCS屬性"), Description("是否允許粘貼。")]

public bool EnablePaste


...{


get ...{ return _EnPaste; }

set


...{

_EnPaste = value;
}


/**//// <summary>

///

/// </summary>

[Category("JCS屬性"), Description("是否右鍵菜單。")]

public bool EnableContextMenu


...{



get ...{ return _EnContextMenu; }

set


...{

_EnContextMenu = value;

}

}



//獲取或設置用於創建新單元格的模板

public override DataGridVIEwCell CellTemplate


...{

get


...{

return base.CellTemplate;

}


set


...{

//

if (value != null && !value.GetType().IsAssignableFrom(typeof(JcsNumTextBoxCell)))


...{

string s = "Cell type is not based upon the JcsNumTextBoxCell.";

throw new InvalidCastException(s);

}


base.CellTemplate = value;

}

}


}

}
3)JcsNumTextBoxEditingControl

using System;

using System.Collections.Generic;

using System.Text;

using System.Windows.Forms;


namespace JcsExpLibary.Numeric_Textbox


...{

public class JcsNumTextBoxEditingControl:JcsInputNum ,IDataGridVIEwEditingControl


...{

protected int rowIndex;

protected DataGridView dataGridVIEw;

protected bool valueChanged = false;


public JcsNumTextBoxEditingControl()


...{


}

//重寫jcsinputnum的ontextchanged

protected override void OnTextChanged(EventArgs e)


...{

base.OnTextChanged(e);

//通知datagridvIEw值已經更改

NotifyDataGridVIEwOfValueChange();

}


//通知DataGridVIEw值已經更改

protected virtual void NotifyDataGridVIEwOfValueChange()


...{

this.valueChanged = true;

if (this.dataGridVIEw != null)


...{

//設置當前單元格有未提交的更改

this.dataGridVIEw.NotifyCurrentCellDirty(true);

}

}



IDataGridViewEditingControl Members#region IDataGridVIEwEditingControl Members


//獲取當鼠標指針位於 DataGridVIEw.EditingPanel 上方但不位於編輯控件上方時所使用的光標

public Cursor EditingPanelCursor


...{

get


...{

return Cursors.IBeam;

}

}



//獲取或設置所在的DataGridVIEw.

public DataGridView EditingControlDataGridVIEw


...{

get


...{

return this.dataGridVIEw;

&nb }


set


...{

this.dataGridVIEw = value;

}

}



//獲取或設置value(按照指定format)

public object EditingControlFormattedValue


...{

set


...{

this.Text = value.ToString();

NotifyDataGridVIEwOfValueChange();

}

get


&nb ...{

return this.Text;

}


}


//檢索單元格的格式化值

public object GetEditingControlFormattedValue(DataGridVIEwDataErrorContexts context)


...{

return this.Text;

}


//確定指定的鍵是應由編輯控件處理的常規輸入鍵,還是應由 DataGridVIEw 處理的特殊鍵

public bool EditingControlWantsInputKey(Keys keyData, bool dataGridVIEwWantsInputKey)


...{

switch (keyData & Keys.KeyCode)


...{

case Keys.Right:

//

if (!(this.SelectionLength == 0

&& this.Selection== this.ToString().Length))


...{

return true;

}

break;


case Keys.Left:

//

if (!(this.SelectionLength == 0

&& this.SelectionStart == 0))


...{

return true;

}

break;


case Keys.Home:

case Keys.End:

if (this.SelectionLength != this.ToString().Length)


...{

return true;

}

break;


case Keys.Prior:

case Keys.Next:

if (this.valueChanged)


...{

return true;

}

break;


case Keys.Delete:

if (this.SelectionLength > 0 || this.SelectionStart < this.ToString().Length)


...{

return true;

}

break;

}


//

return !dataGridVIEwWantsInputKey;

}



//准備接受修改

public void PrepareEditingControlForEdit(bool selectAll)


...{

if (selectAll)


...{

SelectAll();

}

else


...{

//光標設置於末尾

this.SelectionStart = this.ToString().Length;

}

}


//獲取或設置一個值,該值指示每當值更改時,是否需要重新定位單元格的內容

public bool RepositionEditingControlOnValueChange


...{

get


...{

return false;

}

}


//獲取或設置該承載單元格的父行的索引

public int EditingControlRowIndex


...{

get


...{

return this.rowIndex;

}


set


...{

this.rowIndex = value;

}

}




//更改控件的用戶界面 (UI),使之與指定單元格樣式一致

public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridVIEwCellStyle)


...{

this.Font = dataGridVIEwCellStyle.Font;

this.ForeColor = dataGridVIEwCellStyle.ForeColor;

this.BackColor = dataGridVIEwCellStyle.BackColor;

this.TextAlign = translateAlignment(dataGridVIEwCellStyle.Alignment);

}



//獲取或設置一個值,該值指示編輯控件的值是否與承載單元格的值不同

public bool EditingControlValueChanged


...{

get


...{

return valueChanged;

}


set


...{

this.valueChanged = value;

}

}

#endregion // IDataGridVIEwEditingControl.


/**//// Routine to translate between DataGridVIEw

/// content alignments and text box horizontal alignments.

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;

}


throw new ArgumentException("Error: Invalid Content Alignment!");

}

}

}
4)測試代碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using JcsExpLibary.Numeric_Textbox;
namespace WindowsApplication1
...{
public partial class Form9 : Form

...{
public Form9()

...{
InitializeComponent();
InitializeDataGridVIEwColumns();
}
private void InitializeDataGridVIEwColumns()

...{
DataGridVIEwTextBoxColumn dgvtbc;
JcsNumTextBoxColumn jcsnumtextcol;

//
// employee name.
//
dgvtbc = new DataGridVIEwTextBoxColumn();
dgvtbc.HeaderText = "Name";
&nb dgvtbc.Width = 120;
this.dataGridVIEw1.Columns.Add(dgvtbc);

//
// Employee Value
//
jcsnumtextcol = new JcsNumTextBoxColumn();
jcsnumtextcol.HeaderText = "Employee Value";
jcsnumtextcol.isintegral = false;
jcsnumtextcol.IsNegativeNumber = true;
jcsnumtextcol.PointNumber = 2;
jcsnumtextcol.EnableContextMenu = false;
jcsnumtextcol.EnablePaste = false;
jcsnumtextcol.Width = 75;
this.dataGridVIEw1.Columns.Add(jcsnumtextcol);


//
// Address
//
dgvtbc = new DataGridVIEwTextBoxColumn();
dgvtbc.HeaderText = "Address";
dgvtbc.Width = 150;
this.dataGridVIEw1.Columns.Add(dgvtbc);

//
// City
//
dgvtbc = new DataGridVIEwTextBoxColumn();
dgvtbc.HeaderText = "City";
dgvtbc.Width = 75;
this.dataGridVIEw1.Columns.Add(dgvtbc);

//
// Department Code
//
dgvtbc = new DataGridVIEwTextBoxColumn();
dgvtbc.HeaderText = "Department";
dgvtbc.ValueType = typeof(int);
dgvtbc.Width = 75;
this.dataGridVIEw1.Columns.Add(dgvtbc);
}
}
}