(原创文章,转载请注明来源:http://blog.csdn.net/hulihui)
前几天写了博文:
TDataGridViewEx组件中设置行背景颜色的.NET事件实现技术,介绍了如何通过.NET的事件机制,设置DataGridView组件的单元格(行)的背景颜色。其实,这种方法可以推广。例如,本文探讨的设置单元格(行/列)只读(ReadOnly)。
DataGridView的DataGridViewCell、DataGridViewColumn及其自身,均有ReadOnly属性,可以设置一个单元格或列/行只读,在增加列时就可以直接设置ReadOnly。但笔者认为,针对DataGridView,直接设置格/行/列对象的ReadOnly不灵活,特别是指定某些单元格(行/列)只读时。于是,考虑通过事件机制设置指定单元格的ReadOnly,即增加事件 exSetCellReadOnly。
要解决的一个技术问题:如何捕获当前单元格(行/列)?经过比较,笔者重载了DataGridView的OnCellEnter事件,在该事件中判断应用程序是否订阅了exSetCellReadOnly 事件。步骤如下:
下面是TDataGridViewEx中相关的代码(申明事件、激发事件、判断返回参数)
下面是窗体程序中的事件订阅代码
.NET中的委托与事件,给予类与其使用者(订阅者)相互通信的机制,掌握后可以灵活应用到类、组件设计中。本文就事件机制探讨其实现。事实上,可以直接在窗体程序中订阅 DataGridView 的 CellEnter 事件,直接设置 DataGridView 对象的单元格/行/列即可,也就是说本文内容是多余的。笔者最后也删除了 TDataGridViewEx 组件中的相关代码。
DataGridView的DataGridViewCell、DataGridViewColumn及其自身,均有ReadOnly属性,可以设置一个单元格或列/行只读,在增加列时就可以直接设置ReadOnly。但笔者认为,针对DataGridView,直接设置格/行/列对象的ReadOnly不灵活,特别是指定某些单元格(行/列)只读时。于是,考虑通过事件机制设置指定单元格的ReadOnly,即增加事件 exSetCellReadOnly。
要解决的一个技术问题:如何捕获当前单元格(行/列)?经过比较,笔者重载了DataGridView的OnCellEnter事件,在该事件中判断应用程序是否订阅了exSetCellReadOnly 事件。步骤如下:
- 定义事件委托:TSetCellReadOnlyEvent
- 定义事件参数:TSetCellReadOnlyEventArgs
- 申明类型事件:exSetCellReadOnly
- 重载DataGridView的OnCellEnter
- public delegate void TSetCellReadOnlyEvent(object sender, TSetCellReadOnlyEventArgs e);
- public class TSetCellReadOnlyEventArgs : EventArgs
- {
- private int m_RowIndex;
- private int m_ColIndex;
- private bool m_ReadOnly = false;
- public TSetCellReadOnlyEventArgs(int row, int col)
- {
- m_RowIndex = row;
- m_ColIndex = col;
- }
- public int RowIndex
- {
- get { return m_RowIndex; }
- }
- public int ColIndex
- {
- get { return m_ColIndex; }
- }
- public bool ReadOnly
- {
- get { return m_ReadOnly; }
- set { m_ReadOnly = value; }
- }
- }
- public class TDataGridViewEx : DataGridView
- {
- [Description("Set a cell if readonly or not.")]
- public event TSetCellReadOnlyEvent exSetCellReadOnly; // 申明事件委托
- /// <summary>
- /// 进入单元格时, 判断是否为 ReadOnly
- /// </summary>
- protected override void OnCellEnter(DataGridViewCellEventArgs e)
- {
- if (this.exSetCellReadOnly != null)
- {
- TSetCellReadOnlyEventArgs ee = new TSetCellReadOnlyEventArgs(e.RowIndex, e.ColumnIndex);
- this.exSetCellReadOnly(this, ee);
- this.Rows[e.RowIndex].Cells[e.ColumnIndex].ReadOnly = ee.ReadOnly; // 只要客户端订阅了SetReadOnly事件, 则总是设置当前进入单元的ReadOnly属性
- }
- base.OnCellEnter(e);
- }
- }
- private void dataGridView1_exSetCellReadOnly(object sender, CSUST.Data.TSetCellReadOnlyEventArgs e)
- {
- if (e.ColIndex == 2 && e.RowIndex == 2) // 单元格[2,2]只读
- {
- e.ReadOnly = true;
- }
- else if (e.RowIndex == 5) // 行序号5为只读
- {
- e.ReadOnly = true;
- }
- else if (e.ColIndex == 0) // 0列只读
- {
- e.ReadOnly = true;
- }
- }