圖:效果圖
一、 設計初衷
1. 有沒有想過當你的表格中的某些數據需要分類時該如何做?
2. 有沒有想過當表格中的數據根據某一狀態來啟用/禁用某個按鈕?
3. 有沒有想過為了突出某一些數據,所以加顏色來區分?
4. 總得來說,就是如何根據數據來設置行或單元格的樣式?
二、 設計實現
通過以上幾個疑問,最終也歸結為一點:如何根據數據來設置行或單元格的樣式? 其實這個問題,我也糾結了一段時間,后來再詳細的查找嘗試后,不經意間發現在DataGridView中有一個CellFormatting事件,這樣的話就為我的解決方案提供了基礎。
1. 思考之一,對於單元格的格式化,由於是基於內容來改變樣式,所以可以為列(Column)來注冊一個格式化器,因為列的內容類型是一致的。
2. 思考之二,為了能提供在封裝之后的樣式的靈活改變,就應該把格式化器的注冊開放到外部,所以以委托形式來注冊。
綜上考慮,最終設計了這么一個類:
1: public class DataGridCellFormatter : IDisposable2: {3:4: /// <summary>5: /// 值與顯示轉換的委托6: /// </summary>7: /// <param name="columnName">當前列名</param>8: /// <param name="value">當前列值</param>9: /// <returns>轉換后的顯示值</returns>10: public delegate void CellFormatDelegate(string columnName, DataGridViewCellFormattingEventArgs value);11:12: /// <summary>13: /// key:列名,value:注冊的委托14: /// </summary>15: private Dictionary<string, CellFormatDelegate> m_cellFormatters = new Dictionary<string, CellFormatDelegate>();16:17: /// <summary>18: /// 將列轉換注冊到具體的方法19: /// </summary>20: /// <param name="columnName">注冊列名稱</param>21: /// <param name="formatter">注冊列轉換方法</param>22: public void RegisterFormatter(string columnName, CellFormatDelegate formatter)23: {24: if (!string.IsNullOrEmpty(columnName) && formatter != null)25: m_cellFormatters[columnName] = formatter;26: }27:28: /// <summary>29: /// 獲取注冊格式化器30: /// </summary>31: /// <param name="columnName"></param>32: public CellFormatDelegate GetRegisterFormatter(string columnName)33: {34: if (m_cellFormatters.ContainsKey(columnName))35: return m_cellFormatters[columnName];36: return null;37: }38:39: /// <summary>40: /// 執行格式化操作41: /// </summary>42: /// <param name="columnName"></param>43: /// <param name="defaultValue"></param>44: public void RunFormatter(string columnName, DataGridViewCellFormattingEventArgs defaultValue)45: {46: CellFormatDelegate formatter = GetRegisterFormatter(columnName);47: if (formatter == null) return;48: formatter(columnName, defaultValue);49: }50:51: public void Dispose()52: {53: if (m_cellFormatters.Count > 0)54: m_cellFormatters.Clear();55: }56: }
然后再CellFormatting中把格式化器給Hook到DataGridViewEx上面:
1: protected override void OnCellFormatting(DataGridViewCellFormattingEventArgs e)2: {3: //Mark:在這里執行注冊的程序4: this.CellFormatterRegister.RunFormatter(this.Columns[e.ColumnIndex].Name, e);5: base.OnCellFormatting(e);6: }
最后,使用者只要在引用DataGridViewEx的時候,注冊一下想要的列改變就行了:
1: protected void RegisterCellFormatters()2: {3: this.dataGridViewEx1.CellFormatterRegister.RegisterFormatter("Column5",4: new DataGridCellFormatter.CellFormatDelegate(FormatColumn5));5: this.dataGridViewEx1.CellFormatterRegister.RegisterFormatter("Column4",6: new DataGridCellFormatter.CellFormatDelegate(FormatColumn4));7: }8:9: //根據內容改變Column5的文本顏色10: internal void FormatColumn5(string columnName, DataGridViewCellFormattingEventArgs e)11: {12: if (e.Value.ToString().Contains("5"))13: {14: e.CellStyle.ForeColor = Color.Green;15: }16:17: if (e.Value.ToString().Contains("3"))18: {19: e.CellStyle.ForeColor = Color.Red;20: }21: }22:23: // 根據內容設置自定義按鈕列為不可用24: internal void FormatColumn4(string columnName, DataGridViewCellFormattingEventArgs e)25: {26: if (e.Value.ToString().Contains("2"))27: {28: DataGridViewButtonCellEx cell =29: this.dataGridViewEx1.Rows[e.RowIndex].Cells[e.ColumnIndex] as DataGridViewButtonCellEx;30: if (cell != null)31: {32: cell.Enabled = false;33: }34: }35:36: }ok,一切都搞定,讓它自動運行吧。
三、 Demo程序和開源源碼
Demo下載:DataGridCellFormatter@DataGridViewEx.rar
開源地址 :http://sourceforge.net/p/datagridviewex/code-0/3/tree/trunk/DataGridViewEx/

