C#如何自定义DataGridViewColumn来显示TreeView
我们可以自定义DataGridView的DataGridViewColumn来实现自定义的列,下面介绍一下如何通过扩展DataGridViewColumn来实现一个TreeViewColumn
1 TreeViewColumn类
TreeViewColumn继承自DataGridViewColumn,为了动态给TreeViewColumn传入一个TreeView,这里暴露出一个公共属性_root,可以绑定一个初始化的TreeView. 另外需要重写DataGridCell类型的CellTemplate,这里返还一个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,这里就是具体实现其逻辑。一般来说选择树控件的节点后,返回的是一个文本信息,是文本类型,可以继承DataGridViewTextBoxCell,并重写InitializeEditingControl来进行自定义的DataGridView.EditingControl (编辑控件)。
public class TreeViewCell : DataGridViewTextBoxCell
{ public TreeViewCell()
: base()
{ //初始设置
} 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为编辑控件,当用户编辑TreeViewCell时,显示的为树编辑控件,需要继承TreeView,同时实现IDataGridViewEditingControl接口,实现以下方法:

public class TreeViewEditingControl : TreeView, IDataGridViewEditingControl
{
DataGridView dataGridView;
private bool valueChanged = false;
int rowIndex;
public TreeViewEditingControl()
{
try
{
//必须加Roots.tree.Nodes[0].Clone() 否则报错 不能在多处增添或插入项,必须首先将其从当前位置移除或将其克隆
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); } }
为了在不同类之间传递参数,定义一个全局静态类:
/// <summary>
/// 静态类的静态属性,用于在不同class间传递参数
/// </summary>
public static class Roots
{
//从前台绑定树
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>
/// 静态类的静态属性,用于在不同class间传递参数
/// </summary>
public static class Roots
{
//从前台绑定树
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()
{ //初始设置
} 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[0].Clone() 否则报错 不能在多处增添或插入项,必须首先将其从当前位置移除或将其克隆
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); } } }

当编辑无误后,可以在添加列的时候看到TreeViewColumn类型。此类型暴露出一个_root属性,可以绑定外部的一个带数据的TreeView。

运行代码,单击单元格,进入编辑状态,可以看到如下界面:

C#如何自定义DataGridViewColumn来显示TreeView的更多相关文章
- ToastUtil【简单的Toast封装类】【未自定义Toast的显示风格】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 一个简单的Toast封装类. 效果图 API = 6.0 API = 4.4.2 代码分析 实现了不管我们触发多少次Toast调用, ...
- ToastCustomUtil【简单的Toast封装类】【自定义Toast的显示风格】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 ToastUtil + ToastCustom结合.主要解决低版本机型上系统toast显示不好看的问题. 效果图 代码分析 在Toa ...
- iOS8自定义推送显示按钮及推送优化
http://www.jianshu.com/p/803bfaae989e iOS8自定义推送显示按钮及推送优化 字数1435 阅读473 评论0 喜欢2 导语 在iOS8中,推送消息不再只是简单地点 ...
- WPF自定义窗口最大化显示任务栏
原文:WPF自定义窗口最大化显示任务栏 当我们要自定义WPF窗口样式时,通常是采用设计窗口的属性 WindowStyle="None" ,然后为窗口自定义放大,缩小,关闭按钮的样式 ...
- Django(四) 后台管理:创建管理员、注册模型类、自定义管理页面显示内容
后台管理 第1步.本地化:设置语言.时区 修改project1/settings.py #LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'zh-hans' #设置语言 ...
- 怎么自定义DataGridViewColumn(日期列,C#)
参考:https://msdn.microsoft.com/en-us/library/7tas5c80.aspx 未解决的问题:如果日期要设置为null,怎么办? DataGridView控件提供了 ...
- 调试asp.net网页时不显示treeview的原因
在.net中本地调试asp.net网页时,treeview控件显示为文字方式,原因是在http://localhost/下面找不到webctrl_client的路径,解决的方法是把webctrl_cl ...
- yii2-basic后台管理功能开发之三:自定义GridView列显示
在第二篇 yii2-basic后台管理功能开发之二:创建CRUD增删改查 中,我们利用gii工具生成的结果一般并不是我们想要的结果. 我们需要根据自己的需求自定义列显示.我遇到的主要是一下变更: 时间 ...
- 自定义一个只显示年月的DatePicker(UIDatePicker无法实现年月显示)
HooDatePicker 介绍(introduction) ==================================================项目需要一个DatePicker,只显 ...
随机推荐
- PHP上传实现进度条
Web上传文件的三种解决方案
- Tools - VirtualBox
为CentOS虚拟机安装增强功能 启动CentOS虚拟机,点击"菜单 -> 设备 -> 安装增强功能". vboxadd的映像文件将会被挂载到虚拟机,在桌面也可以看到, ...
- 【Android】[转] Android中Bitmap,byte[],Drawable相互转化
一.相关概念 1.Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable) ...
- 对比MFC资源文件谈谈WPF布局方式
对比MFC资源文件谈谈WPF布局方式 MFC方式 对于传统的MFC基于UI的应用程序设计通常分两步走,首先是设计UI,使用的是RC文件,然后是代码文件,对RC文件进行操作,如下面Figure 1 的基 ...
- APPSCAN使用外部浏览器
在使用appscan扫描时,自带浏览器可能存在兼容性问题(比如HTML5),故需要用到其他浏览器.在做139邮箱HTML5项目,需要使用chrome浏览器进行扫描.因此分享下如何使用外部浏览器,将之前 ...
- 2013年最佳的16个 Photoshop 设计教程推荐
使用 Photoshop 的时候,没有基础操作知识的话,用起来会非常困难,所以你应该阅读一些教程才能应用它们在你的工作中.在这篇文章中你看到的 Photoshop 教程的集合是2013年发布的最优秀的 ...
- 转 Windows+VS2013爆详细Caffe编译安装教程
1. 安装cuda Cuda是英伟达推出的GPU加速运算平台 我这里安装的是cuda7.5,已经安装过的忽略,还没有安装过的这里有安装教程.windows下面安装还是非常简单的. 点击打开链接 ...
- ES6笔记(7)-- Promise异步编程
系列文章 -- ES6笔记系列 很久很久以前,在做Node.js聊天室,使用MongoDB数据服务的时候就遇到了多重回调嵌套导致代码混乱的问题. JS异步编程有利有弊,Promise的出现,改善了这一 ...
- C#协变和逆变
我们知道在C#中,是可以将派生类的实例赋值给基类对象的.
- 插入排序---希尔插入排序算法(Javascript版)
取一个小于n的整数作为第一个增量,把序列分组.所有距离为增量的倍数的元素放在同一个组中.先在各组内进行直接插入排序:然后,取第二个增量(第二个<第一个)重复上述的分组和排序,直至所取的增量=1, ...