using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Data;
/*表格树控件说明
* 此控件继承DataGrid 新增属性说明:
* 1.TreeParentCode:顶级根节点parentcode
* 2.TreeDisplayDeep:展现表格树深度默认为1
* 3.SumColumns:自动汇总到根节点的字段集合 针对 decimal类型
* 4.新增树状列模板TemplateTreeColumn 此模板继承了TemplateColumn 重写了方法InitializeCell
* 客户端新增特性配置说明
* 1.固定列 配置 ItemStyle-CssClass='TdLockedClass'
* 2.固定表头 配置 HeaderStyle-CssClass='TRLockedClass'
* 3.文本框 input 或 <asp:TextBox 配置事件οnchange='sumParent(this);' 数字改变相应所有父节点也随着改变 针对数字型 其他不支持
* 不过可以自定义js
* 报表说明:
* 1.DataGridTree.EnableViewState=false;提高加载速度
* 2.动态定义列 实现 BoundColumn column = new BoundColumn();
column.HeaderText = "动态列";
column.DataField = "unitname";
datagridnew.Columns.Add(column);
* 也可以自定义默认模板 动态加载模板 定义模板例子TemplateTreeColumn,不用继承TemplateColumn,实现接口 ITemplate InitializeCell 方法就可以了
* 不足之处:1.对于复杂多行表头 不知 如何实现
* 2.表头和列固定 数据量大时 会影响反映速度 一千左右的数据量 还时没问题的 数据量在大的话 课考虑采用ajax动态加载 目前此功能还没实现
*
*/
namespace System.Web.UI.WebControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:DataGridTree runat=server></{0}:DataGridTree>")]
public class DataGridTree : DataGrid
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("454455454")]
[Localizable(true)]
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}
set
{
ViewState["Text"] = value;
}
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string TreeParentCode
{
get
{
if (ViewState["TreeParentCode"] == null)
{
return "";
}
return ViewState["TreeParentCode"].ToString();
}
set { ViewState["TreeParentCode"] = value; }
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("1")]
[Localizable(true)]
public int TreeDisplayDeep
{
get
{
if (ViewState["TreeDisplayDeep"] == null)
{
return 1;
}
int result = (int)ViewState["TreeDisplayDeep"];
if (result < 1)
{
return 1;
}
else
{
return result;
}
}
set
{
ViewState["TreeDisplayDeep"] = value;
}
}
public List<string> SumColumns = new List<string>();
private DataTable _DataSourceTable;
private DataTable DataSourceTable
{
get
{
if (_DataSourceTable == null)
{
_DataSourceTable = (DataTable)base.DataSource;
}
return _DataSourceTable;
}
set
{
_DataSourceTable = value;
}
}
public override void DataBind()
{
if (base.DataSource is DataSet)
{
DataSourceTable = ((DataSet)base.DataSource).Tables[0];
}
else if (base.DataSource is DataTable)
{
DataSourceTable = ((DataTable)base.DataSource);
}
else
{
throw new ArgumentOutOfRangeException("只支持DataSet和DataTable数据源", new Exception());
}
base.DataSource = LoadDataSourceTableTree();
base.DataBind();
}
protected override void Render(HtmlTextWriter writer)
{
writer.Write(@"<div class='divclass' id='tbltree-container'>
<script language='javascript' type='text/javascript'>var container=document.getElementById('tbltree-container');</script>");
base.Render(writer);
writer.Write("</div>");
}
private DataTable LoadDataSourceTableTree()
{
DataSourceTable.Columns.Add("nodeHtml", typeof(string));//保存 Node节点html
DataSourceTable.Columns.Add("parentFullCode", typeof(string));// js事件根据parentFullCode 寻找字节点
DataSourceTable.Columns.Add("imgtag", typeof(string));//imgtag:1:plus图片字节隐藏状态;0:minus图片字节点显示状态
DataSourceTable.Columns.Add("display", typeof(string));//该节点显示状态
DataTable DataSourceTableTree = DataSourceTable.Clone();
List<DataRow> rowsTree = new List<DataRow>();
List<DataRow> list = FindRows(TreeParentCode);
DataRow treeRow = DataSourceTable.NewRow();
treeRow["parentFullCode"] = "";
if (!string.IsNullOrEmpty(TreeParentCode))
{
treeRow["code"] = TreeParentCode;
}
//递归生成树状结构表
FindRowNodes(treeRow, list, "", rowsTree, 1);
//rowsTree中的DataRow结构属于DataSourceTableTree
DataRow newrow;
foreach (DataRow row in rowsTree)
{
newrow = DataSourceTableTree.NewRow();
foreach (DataColumn column in DataSourceTableTree.Columns)
{
newrow[column.ColumnName] = row[column.ColumnName];
}
DataSourceTableTree.Rows.Add(newrow);
}
DataSourceTable = DataSourceTableTree;
return DataSourceTable;
}
/// <summary>
/// 查找并初始化字节点数据
/// </summary>
/// <param name="parentRow">父节点DataRow</param>
/// <param name="childRows">子节点集合</param>
/// <param name="imgList">"1:0:0"节点前图片标记1:竖线图片0:空白图片</param>
/// <param name="rowsTree">构造树的List<DataRow></param>
/// <param name="deep">层级 深度</param>
/// <returns>子点数据源集合</returns>
private void FindRowNodes(DataRow parentRow, List<DataRow> childRows, string imgList, List<DataRow> rowsTree, int deep)
{
int count = childRows.Count;
int i = 1;
int imgtag = 1;//imgtag:1:plus图片字节隐藏状态;0:minus图片字节点显示状态
foreach (DataRow row in childRows)
{
row["parentFullCode"] = parentRow["parentFullCode"].ToString() + parentRow["code"] + "-";
if (deep <= TreeDisplayDeep)
{
row["display"] = "";
}
else
{
row["display"] = "none";
}
if (deep < TreeDisplayDeep)//下一级字节点显示状态
{
imgtag = 0; //0:minus图片字节点显示状态
}
string childImagList = "";//"1:0:0"节点前图片标记1:竖线图片0:空白图片
string indexTag = "";//1:末级节点0:其他
if (count == i)
{
indexTag = "1";
childImagList = imgList + ":0";
}
else
{
childImagList = imgList + ":1";
indexTag = "0";
}
List<DataRow> list = FindRows(row["code"].ToString());
if (list.Count > 0)
{
List<DataRow> rowsChildTree = new List<DataRow>();
FindRowNodes(row, list, childImagList, rowsChildTree, deep + 1);
LoadParentRow(parentRow, row, imgList, indexTag, imgtag);
rowsTree.Add(row);
rowsTree.AddRange(rowsChildTree);
}
else
{
LoadLeafRow(parentRow, row, imgList, indexTag);
rowsTree.Add(row);
}
i++;
}
}
/// <summary>
///
/// </summary>
/// <param name="parentRow"></param>
/// <param name="row"></param>
/// <param name="imgList"></param>
/// <param name="indexTag"></param>
private void LoadLeafRow(DataRow parentRow, DataRow row, string imgList, string indexTag)
{
string imgstr = GetImageListStr(imgList);
if (indexTag == "1")
{
imgstr += "<img src=\"../Images/tabletree/joinbottom.gif\"><img src=\"../Images/tabletree/page.gif\">";
}
else
{
imgstr += "<img src=\"../Images/tabletree/join.gif\"><img src=\"../Images/tabletree/page.gif\">";
}
row["nodeHtml"] = imgstr;
//汇总到根节点
foreach (string column in SumColumns)
{
try
{
parentRow[column] = Convert.ToDecimal(parentRow[column]) + Convert.ToDecimal(row[column]);
}
catch (Exception ex)
{
if (parentRow[column] == DBNull.Value)
{
parentRow[column] = 0;
}
if (row[column] == DBNull.Value)
{
row[column] = 0;
}
parentRow[column] = Convert.ToDecimal(parentRow[column]) + Convert.ToDecimal(row[column]);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="parentRow"></param>
/// <param name="row"></param>
/// <param name="imgList"></param>
/// <param name="indexTag"></param>
/// <param name="imgtag"></param>
private void LoadParentRow(DataRow parentRow, DataRow row, string imgList, string indexTag, int imgtag)
{
row["imgtag"] = imgtag;//imgtag:1:plus图片字节点处于隐藏状态;0:minus图片字节点处于显示状态
string imgstr = GetImageListStr(imgList);
if (imgtag == 1)
{
if (indexTag == "1")
{
imgstr += string.Format("<img src=\"../Images/tabletree/plusbottom.gif\" imgtag=\"1\" {0}><img src=\"../Images/tabletree/musicfolder.gif\">", GetShowTableTree(row));
}
else
{
imgstr += string.Format("<img src=\"../Images/tabletree/plus.gif\" imgtag=\"1\" {0}><img src=\"../Images/tabletree/musicfolder.gif\">", GetShowTableTree(row));
}
}
else
{
if (indexTag == "1")
{
imgstr += string.Format("<img src=\"../Images/tabletree/minusbottom.gif\" imgtag=\"0\" {0}><img src=\"../Images/tabletree/musicfolder.gif\">", GetShowTableTree(row));
}
else
{
imgstr += string.Format("<img src=\"../Images/tabletree/minus.gif\" imgtag=\"0\" {0}><img src=\"../Images/tabletree/musicfolder.gif\">", GetShowTableTree(row));
}
}
row["nodeHtml"] = imgstr;
//汇总到根节点
foreach (string column in SumColumns)
{
try
{
parentRow[column] = Convert.ToDecimal(parentRow[column]) + Convert.ToDecimal(row[column]);
}
catch (Exception ex)
{
if (parentRow[column] == DBNull.Value)
{
parentRow[column] = 0;
}
if (row[column] == DBNull.Value)
{
row[column] = 0;
}
parentRow[column] = Convert.ToDecimal(parentRow[column]) + Convert.ToDecimal(row[column]);
}
}
}
private static string GetShowTableTree(DataRow row)
{
return "οnclick=\"showTableTree(this,'" + row["Code"].ToString() + "','" + row["parentFullCode"] + "');\"";
}
private string GetImageListStr(string imagelist)
{
StringBuilder sb = new StringBuilder();
string[] liststr = imagelist.Split(new char[] { ':' });
foreach (string str in liststr)
{
if (str == "0")
{
sb.Append("<img src='../Images/tabletree/empty.gif'>");
}
else if (str == "1")
{
sb.Append("<img src='../Images/tabletree/line.gif'>");
}
}
return sb.ToString();
}
private List<DataRow> FindRows(string parentcode)
{
List<DataRow> list = new List<DataRow>();
foreach (DataRow row in DataSourceTable.Rows)
{
if (row["parentcode"].ToString().Trim() == parentcode.Trim())
{
list.Add(row);
}
}
return list;
}
}
[AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class TemplateTreeColumn : TemplateColumn
{
// Label label;
public override void InitializeCell(TableCell cell, int columnIndex, ListItemType itemType)
{
base.InitializeCell(cell, columnIndex, itemType);
if (itemType == ListItemType.Header)
{
return;
}
else
{
InstantiateIn(cell);
}
}
public void InstantiateIn(Control container)
{
Label label = new Label();
label.DataBinding+= new EventHandler(this.BindData);
container.Controls.AddAt(0,label);
}
void BindData(object o, EventArgs e)
{
Label label = (Label)o;
Control Container = label.NamingContainer;
DataGridItem item=(DataGridItem)Container;
if (item.DataSetIndex >= 0)
{
item.Attributes["parentfullcode"] = DataBinder.Eval(Container, "DataItem.parentFullCode").ToString();
item.Attributes["code"] = DataBinder.Eval(Container, "DataItem.code").ToString();
item.Attributes["imgtag"] = DataBinder.Eval(Container, "DataItem.imgtag").ToString();//imgtag:1:plus图片字节隐藏状态;0:minus图片字节点显示状态
item.Style.Add("display", DataBinder.Eval(Container, "DataItem.display").ToString());
label.Text = DataBinder.Eval(Container, "DataItem.nodeHtml").ToString();
}
}
}
}