C#自定義DataGridViewColumn顯示TreeView
我們可以自定義DataGridView的DataGridViewColumn來實(shí)現(xiàn)自定義的列,下面介紹一下如何通過擴(kuò)展DataGridViewColumn來實(shí)現(xiàn)一個(gè)TreeViewColumn
1.TreeViewColumn類
TreeViewColumn繼承自DataGridViewColumn,為了動(dòng)態(tài)給TreeViewColumn傳入一個(gè)TreeView,這里暴露出一個(gè)公共屬性_root,可以綁定一個(gè)初始化的TreeView. 另外需要重寫DataGridCell類型的CellTemplate,這里返還一個(gè)TreeViewCell(需要自定義)
/// <summary>
/// Host TreeView In DataGridView Cell
/// </summary>
public class TreeViewColumn : DataGridViewColumn
{
public TreeViewColumn()
: base(new TreeViewCell())
{
}
[Description("Set TreeView Root in DataGridView Cell"), Category("TreeView")]
public TreeView _root
{
get{return Roots.tree;}
set{Roots.tree=value;}
}
public override DataGridViewCell CellTemplate
{
get
{
return base.CellTemplate;
}
set
{
// Ensure that the cell used for the template is a TreeViewCell.
if (value != null &&
!value.GetType().IsAssignableFrom(typeof(TreeViewCell)))
{
throw new InvalidCastException("Must be a TreeViewCell");
}
base.CellTemplate = value;
}
}
}
2.TreeViewCell類
上面TreeViewColumn重寫了CellTemplate,返回的就是自定義的TreeViewCell,這里就是具體實(shí)現(xiàn)其邏輯。一般來說選擇樹控件的節(jié)點(diǎn)后,返回的是一個(gè)文本信息,是文本類型,可以繼承DataGridViewTextBoxCell,并重寫InitializeEditingControl來進(jìn)行自定義的DataGridView.EditingControl (編輯控件)。
public class TreeViewCell : DataGridViewTextBoxCell
{
public TreeViewCell()
: base()
{
//初始設(shè)置
}
public override void InitializeEditingControl(int rowIndex, object
initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{
// Set the value of the editing control to the current cell value.
base.InitializeEditingControl(rowIndex, initialFormattedValue,
dataGridViewCellStyle);
TreeViewEditingControl ctl =
DataGridView.EditingControl as TreeViewEditingControl;
// Use the default row value when Value property is null.
if (this.Value == null)
{
ctl.SelectedNode =new TreeNode( this.DefaultNewRowValue.ToString());
}
else
{
ctl.SelectedNode = new TreeNode(this.Value.ToString());
}
}
public override Type EditType
{
get
{
// Return the type of the editing control that CalendarCell uses.
return typeof(TreeViewEditingControl);
}
}
public override Type ValueType
{
get
{
// Return the type of the value that CalendarCell contains.
return typeof(String);
}
}
public override object DefaultNewRowValue
{
get
{
// Use the current date and time as the default value.
return "";
}
}
}
3.TreeViewEditingControl類
TreeViewEditingControl為編輯控件,當(dāng)用戶編輯TreeViewCell時(shí),顯示的為樹編輯控件,需要繼承TreeView,同時(shí)實(shí)現(xiàn)IDataGridViewEditingControl接口,實(shí)現(xiàn)以下方法:

public class TreeViewEditingControl : TreeView, IDataGridViewEditingControl
{
DataGridView dataGridView;
private bool valueChanged = false;
int rowIndex;
public TreeViewEditingControl()
{
try
{
//必須加Roots.tree.Nodes[].Clone() 否則報(bào)錯(cuò) 不能在多處增添或插入項(xiàng),必須首先將其從當(dāng)前位置移除或?qū)⑵淇寺?
this.Nodes.Add(Roots.tree.Nodes[].Clone() as TreeNode);
this.SelectedNode = this.Nodes[];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// Implements the IDataGridViewEditingControl.EditingControlFormattedValue
// property.
public object EditingControlFormattedValue
{
get
{
return this.SelectedNode.Text;
}
set
{
if (value is String)
{
try
{
// This will throw an exception of the string is
// null, empty, or not in the format of a date.
this.SelectedNode = new TreeNode((String)value);
}
catch
{
// In the case of an exception, just use the
// default value so we're not left with a null
// value.
this.SelectedNode = new TreeNode("");
}
}
}
}
// Implements the
// IDataGridViewEditingControl.GetEditingControlFormattedValue method.
public object GetEditingControlFormattedValue(
DataGridViewDataErrorContexts context)
{
return EditingControlFormattedValue;
}
// Implements the
// IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
public void ApplyCellStyleToEditingControl(
DataGridViewCellStyle dataGridViewCellStyle)
{
this.Font = dataGridViewCellStyle.Font;
this.ForeColor = dataGridViewCellStyle.ForeColor;
this.BackColor = dataGridViewCellStyle.BackColor;
}
// Implements the IDataGridViewEditingControl.EditingControlRowIndex
// property.
public int EditingControlRowIndex
{
get
{
return rowIndex;
}
set
{
rowIndex = value;
}
}
// Implements the IDataGridViewEditingControl.EditingControlWantsInputKey
// method.
public bool EditingControlWantsInputKey(
Keys key, bool dataGridViewWantsInputKey)
{
// Let the TreeViewPicker handle the keys listed.
switch (key & Keys.KeyCode)
{
case Keys.Left:
case Keys.Up:
case Keys.Down:
case Keys.Right:
case Keys.Home:
case Keys.End:
case Keys.PageDown:
case Keys.PageUp:
return true;
default:
return !dataGridViewWantsInputKey;
}
}
// Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit
// method.
public void PrepareEditingControlForEdit(bool selectAll)
{
// No preparation needs to be done.
}
// Implements the IDataGridViewEditingControl
// .RepositionEditingControlOnValueChange property.
public bool RepositionEditingControlOnValueChange
{
get
{
return false;
}
}
// Implements the IDataGridViewEditingControl
// .EditingControlDataGridView property.
public DataGridView EditingControlDataGridView
{
get
{
return dataGridView;
}
set
{
dataGridView = value;
}
}
// Implements the IDataGridViewEditingControl
// .EditingControlValueChanged property.
public bool EditingControlValueChanged
{
get
{
return valueChanged;
}
set
{
valueChanged = value;
}
}
// Implements the IDataGridViewEditingControl
// .EditingPanelCursor property.
public Cursor EditingPanelCursor
{
get
{
return base.Cursor;
}
}
protected override void OnAfterExpand(TreeViewEventArgs e)
{
base.OnAfterExpand(e);
this.dataGridView.Columns[this.dataGridView.CurrentCell.ColumnIndex].Width = this.Width+;
this.dataGridView.Rows[this.dataGridView.CurrentCell.RowIndex].Height = this.Height+;
}
protected override void OnAfterSelect(TreeViewEventArgs e)
{
// Notify the DataGridView that the contents of the cell
// have changed.
valueChanged = true;
this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
base.OnAfterSelect(e);
}
}
為了在不同類之間傳遞參數(shù),定義一個(gè)全局靜態(tài)類:
/// <summary>
/// 靜態(tài)類的靜態(tài)屬性,用于在不同class間傳遞參數(shù)
/// </summary>
public static class Roots
{
//從前臺(tái)綁定樹
public static TreeView tree = null;
}
完整代碼為:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
namespace Host_Controls_in_Windows_Forms_DataGridView_Cells
{
/// <summary>
/// 靜態(tài)類的靜態(tài)屬性,用于在不同class間傳遞參數(shù)
/// </summary>
public static class Roots
{
//從前臺(tái)綁定樹
public static TreeView tree = null;
}
/// <summary>
/// Host TreeView In DataGridView Cell
/// </summary>
public class TreeViewColumn : DataGridViewColumn
{
public TreeViewColumn()
: base(new TreeViewCell())
{
}
[Description("Set TreeView Root in DataGridView Cell"), Category("TreeView")]
public TreeView _root
{
get{return Roots.tree;}
set{Roots.tree=value;}
}
public override DataGridViewCell CellTemplate
{
get
{
return base.CellTemplate;
}
set
{
// Ensure that the cell used for the template is a TreeViewCell.
if (value != null &&
!value.GetType().IsAssignableFrom(typeof(TreeViewCell)))
{
throw new InvalidCastException("Must be a TreeViewCell");
}
base.CellTemplate = value;
}
}
}
//----------------------------------------------------------------------
public class TreeViewCell : DataGridViewTextBoxCell
{
public TreeViewCell()
: base()
{
//初始設(shè)置
}
public override void InitializeEditingControl(int rowIndex, object
initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{
// Set the value of the editing control to the current cell value.
base.InitializeEditingControl(rowIndex, initialFormattedValue,
dataGridViewCellStyle);
TreeViewEditingControl ctl =
DataGridView.EditingControl as TreeViewEditingControl;
// Use the default row value when Value property is null.
if (this.Value == null)
{
ctl.SelectedNode =new TreeNode( this.DefaultNewRowValue.ToString());
}
else
{
ctl.SelectedNode = new TreeNode(this.Value.ToString());
}
}
public override Type EditType
{
get
{
// Return the type of the editing control that CalendarCell uses.
return typeof(TreeViewEditingControl);
}
}
public override Type ValueType
{
get
{
// Return the type of the value that CalendarCell contains.
return typeof(String);
}
}
public override object DefaultNewRowValue
{
get
{
// Use the current date and time as the default value.
return "";
}
}
}
//-----------------------------------------------------------------
public class TreeViewEditingControl : TreeView, IDataGridViewEditingControl
{
DataGridView dataGridView;
private bool valueChanged = false;
int rowIndex;
public TreeViewEditingControl()
{
try
{
//必須加Roots.tree.Nodes[].Clone() 否則報(bào)錯(cuò) 不能在多處增添或插入項(xiàng),必須首先將其從當(dāng)前位置移除或?qū)⑵淇寺?
this.Nodes.Add(Roots.tree.Nodes[].Clone() as TreeNode);
this.SelectedNode = this.Nodes[];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// Implements the IDataGridViewEditingControl.EditingControlFormattedValue
// property.
public object EditingControlFormattedValue
{
get
{
return this.SelectedNode.Text;
}
set
{
if (value is String)
{
try
{
// This will throw an exception of the string is
// null, empty, or not in the format of a date.
this.SelectedNode = new TreeNode((String)value);
}
catch
{
// In the case of an exception, just use the
// default value so we're not left with a null
// value.
this.SelectedNode = new TreeNode("");
}
}
}
}
// Implements the
// IDataGridViewEditingControl.GetEditingControlFormattedValue method.
public object GetEditingControlFormattedValue(
DataGridViewDataErrorContexts context)
{
return EditingControlFormattedValue;
}
// Implements the
// IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
public void ApplyCellStyleToEditingControl(
DataGridViewCellStyle dataGridViewCellStyle)
{
this.Font = dataGridViewCellStyle.Font;
this.ForeColor = dataGridViewCellStyle.ForeColor;
this.BackColor = dataGridViewCellStyle.BackColor;
}
// Implements the IDataGridViewEditingControl.EditingControlRowIndex
// property.
public int EditingControlRowIndex
{
get
{
return rowIndex;
}
set
{
rowIndex = value;
}
}
// Implements the IDataGridViewEditingControl.EditingControlWantsInputKey
// method.
public bool EditingControlWantsInputKey(
Keys key, bool dataGridViewWantsInputKey)
{
// Let the TreeViewPicker handle the keys listed.
switch (key & Keys.KeyCode)
{
case Keys.Left:
case Keys.Up:
case Keys.Down:
case Keys.Right:
case Keys.Home:
case Keys.End:
case Keys.PageDown:
case Keys.PageUp:
return true;
default:
return !dataGridViewWantsInputKey;
}
}
// Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit
// method.
public void PrepareEditingControlForEdit(bool selectAll)
{
// No preparation needs to be done.
}
// Implements the IDataGridViewEditingControl
// .RepositionEditingControlOnValueChange property.
public bool RepositionEditingControlOnValueChange
{
get
{
return false;
}
}
// Implements the IDataGridViewEditingControl
// .EditingControlDataGridView property.
public DataGridView EditingControlDataGridView
{
get
{
return dataGridView;
}
set
{
dataGridView = value;
}
}
// Implements the IDataGridViewEditingControl
// .EditingControlValueChanged property.
public bool EditingControlValueChanged
{
get
{
return valueChanged;
}
set
{
valueChanged = value;
}
}
// Implements the IDataGridViewEditingControl
// .EditingPanelCursor property.
public Cursor EditingPanelCursor
{
get
{
return base.Cursor;
}
}
protected override void OnAfterExpand(TreeViewEventArgs e)
{
base.OnAfterExpand(e);
this.dataGridView.Columns[this.dataGridView.CurrentCell.ColumnIndex].Width = this.Width+;
this.dataGridView.Rows[this.dataGridView.CurrentCell.RowIndex].Height = this.Height+;
}
protected override void OnAfterSelect(TreeViewEventArgs e)
{
// Notify the DataGridView that the contents of the cell
// have changed.
valueChanged = true;
this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
base.OnAfterSelect(e);
}
}
}

當(dāng)編輯無誤后,可以在添加列的時(shí)候看到TreeViewColumn類型。此類型暴露出一個(gè)_root屬性,可以綁定外部的一個(gè)帶數(shù)據(jù)的TreeView。

運(yùn)行代碼,單擊單元格,進(jìn)入編輯狀態(tài),可以看到如下界面:

以上內(nèi)容是小編給大家介紹的C#自定義DataGridViewColumn顯示TreeView 的全部敘述,希望大家喜歡。
相關(guān)文章
基于WPF實(shí)現(xiàn)經(jīng)典紙牌游戲
這篇文章主要為大家詳細(xì)介紹了如何溧陽WPF實(shí)現(xiàn)經(jīng)典紙牌游戲,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)WPF有一定的幫助,需要的可以參考一下2023-02-02
使用C#如何創(chuàng)建人名或其他物體隨機(jī)分組
文章描述了一個(gè)隨機(jī)分配人員到多個(gè)團(tuán)隊(duì)的代碼示例,包括將人員列表隨機(jī)化并根據(jù)組數(shù)分配到不同組,最后按組號(hào)排序顯示結(jié)果2025-01-01
Unity的AssetPostprocessor之Model函數(shù)使用實(shí)戰(zhàn)
這篇文章主要為大家介紹了Unity的AssetPostprocessor之Model函數(shù)使用實(shí)戰(zhàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
WPF中的ListBox實(shí)現(xiàn)按塊顯示元素的方法
這篇文章主要介紹了WPF中的ListBox實(shí)現(xiàn)按塊顯示元素的方法,涉及ListBox屬性設(shè)置相關(guān)操作技巧,需要的朋友可以參考下2016-09-09
c#多線程中Lock()關(guān)鍵字的用法小結(jié)
本篇文章主要是對(duì)c#多線程中Lock()關(guān)鍵字的用法進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助2014-01-01

