FineUI开源版之TreeGrid(修改)

时间:2024-08-07 14:35:20

上篇文章中做了简单实现,但是还是有bug的,还需要在外面写事件的处理,今天又进行修改了。

下面放出代码,同样的  hzh modify标记的就是我进行修改的地方

grid.cs 添加代码

   #region hzh modify
/// <summary>
/// 是否启用树(扩展)
/// </summary>
[Category(CategoryName.OPTIONS)]
[DefaultValue(null)]
[Description("是否启用树(扩展)")]
public bool EnableTree
{
get
{
object obj = FState["EnableTree"];
return obj == null ? false : (bool)obj;
}
set
{
FState["EnableTree"] = value;
if (value)
{
EnableRowClickEvent = false;
}
}
} /// <summary>
/// 是否展开树(扩展)
/// </summary>
[Category(CategoryName.OPTIONS)]
[DefaultValue(null)]
[Description("是否展开树(扩展)")]
public bool ExpandAll
{
get
{
object obj = FState["ExpandAll"];
return obj == null ? true : (bool)obj;
}
set
{
FState["ExpandAll"] = value;
if (value)
{
EnableRowClickEvent = false;
}
}
}
/// <summary>
/// 树节点列名(扩展)
/// </summary>
[Category(CategoryName.OPTIONS)]
[DefaultValue(null)]
[Description("树节点列名(扩展)")]
public string TreeName
{
get
{
object obj = FState["TreeName"];
return obj == null ? "" : (string)obj;
}
set
{
FState["TreeName"] = value;
}
} /// <summary>
/// 主键ID(扩展)
/// </summary>
[Category(CategoryName.OPTIONS)]
[DefaultValue(null)]
[Description("主键ID(扩展)")]
public string TreeDataIDField
{
get
{
object obj = FState["TreeDataIDField"];
return obj == null ? "" : (string)obj;
}
set
{
FState["TreeDataIDField"] = value;
}
}
/// <summary>
/// 父节点列名(扩展)
/// </summary>
[Category(CategoryName.OPTIONS)]
[DefaultValue(null)]
[Description("父节点列名(扩展)")]
public string TreeDataParentIDField
{
get
{
object obj = FState["TreeDataParentIDField"];
return obj == null ? "" : (string)obj;
}
set
{
FState["TreeDataParentIDField"] = value;
}
} /// <summary>
/// 得到当然行的层级(扩展)
/// </summary>
/// <param name="row">当前行</param>
/// <param name="Rows">行数据集</param>
/// <returns>层级</returns>
private int GetLevelNub(GridRow row, GridRowCollection Rows)
{
int lub = ;
//ID所在列
int IDindex = FindColumn(TreeDataIDField).ColumnIndex;
//父ID所在列
int ParentIDindex = FindColumn(TreeDataParentIDField).ColumnIndex;
//如果过是第第一级就是0
if (row.Values[ParentIDindex].ToString() == "" || row.Values[ParentIDindex].ToString() == "")
{
return lub;
}
else
{
foreach (GridRow gr in Rows)
{
//如果有父级
if (gr.Values[IDindex].ToString() == row.Values[ParentIDindex].ToString())
{
//层级加1
lub++;
//查看父级的父级
int nub = GetLevelNub(gr, Rows);
lub += nub == ? : nub;
}
}
}
return lub;
} private List<GridRow> InsertRowToList(List<GridRow> toList, List<GridRow> sourceRows, int idindex, int pridindex)
{
for (int i = toList.Count - ; i >= ; i--)
{
GridRow torow = toList[i];
bool ismodify = false;
if (sourceRows == null || sourceRows.Count <= )
return toList;
for (int j = sourceRows.Count - ; j >= ; j--)
{
GridRow baserow = sourceRows[j];
if (baserow.Values[pridindex].ToString() != "" && baserow.Values[pridindex].ToString() == torow.Values[idindex].ToString())
{
toList.Insert(i + , baserow);
sourceRows.RemoveAt(j);
ismodify = true;
}
}
if (sourceRows.Count <= )
{
sourceRows.Clear();
sourceRows = null;
return toList;
}
if (ismodify == false)
{
if (sourceRows.Count > )
{
foreach (GridRow item in sourceRows)
{
toList.Add(item);
}
sourceRows.Clear();
sourceRows = null;
}
return toList;
}
}
return InsertRowToList(toList, sourceRows, idindex, pridindex);
} /// <summary>
/// 对rows进行重新排序(扩展)
/// </summary>
private void SortTreeRows()
{
List<GridRow> sourceRows = new List<GridRow>();
foreach (GridRow row in Rows)
{
sourceRows.Add(row);
}
Rows.Clear(); List<GridRow> toList = new List<GridRow>(); int pidindex = FindColumn(TreeDataParentIDField).ColumnIndex;
int idindex = FindColumn(TreeDataIDField).ColumnIndex;
for (int i = sourceRows.Count - ; i >= ; i--)
{
GridRow row = sourceRows[i];
if (row.Values[pidindex].ToString() == "" || row.Values[pidindex].ToString() == "")
{
toList.Insert(, row);
sourceRows.RemoveAt(i);
}
} toList = InsertRowToList(toList, sourceRows, idindex, pidindex);
toList.ForEach(p => Rows.Add(p));
for (int i = ; i < Rows.Count; i++)
{
Rows[i].RowIndex = i;
}
toList.Clear();
toList = null;
} /// <summary>
/// 给树赋值(扩展)
/// </summary>
private void SetValueTree()
{
if (EnableTree)
{
foreach (GridRow row in Rows)
{
//下级行数
string Nextindex = GetNextIndex(row, Rows);
//默认图标
Icon iconindex = FineUI.Icon.ControlBlankBlue;
// string iconname = "page.png";
//图片ID,点击用,绑定事件
string imgid = ClientID + "_tree_icon_" + row.RowIndex;
//父节点图标
if (Nextindex != "")
{
if (ExpandAll)
{
iconindex = FineUI.Icon.ControlRemoveBlue;
//设置展开行
RowCollapsed.Add(row.RowIndex.ToString());
}
else
{
iconindex = FineUI.Icon.ControlAddBlue;
}
// iconname = "folder.png"; //加入图标和ID,注意加过的就不加了
if (row.Values[FindColumn(TreeName).ColumnIndex].ToString().IndexOf(ClientID + "_tree_icon_") < )
{
row.Values[FindColumn(TreeName).ColumnIndex] = "<img id=\"" + imgid + "\" src=\"" + IconHelper.GetResolvedIconUrl(iconindex) + "\" width=\"16\" height=\"16\" style=\"margin-top:-5px;margin-bottom:-2px;cursor: pointer\"/>" + row.Values[];
}
}
}
}
} /// <summary>
/// 得到下级行号
/// </summary>
/// <param name="row">本节点</param>
/// <param name="Rows">集合</param>
/// <returns>集合以,隔开</returns>
private string GetNextIndex(GridRow row, GridRowCollection Rows)
{
string topindex = "";
int pridindex = FindColumn(TreeDataParentIDField).ColumnIndex;
int idindex = FindColumn(TreeDataIDField).ColumnIndex;
foreach (GridRow gr in Rows)
{
//父ID等于本ID添加到集合
if (gr.Values[pridindex].ToString() != "" && gr.Values[pridindex].ToString() == row.Values[idindex].ToString())
{
topindex += topindex == "" ? gr.RowIndex.ToString() : "," + gr.RowIndex.ToString();
}
}
return topindex;
} /// <summary>
/// 得到所有子类行号
/// </summary>
/// <param name="row">本节点</param>
/// <param name="Rows">集合</param>
/// <param name="strIndexs">集合以,隔开</param>
/// <returns>集合以,隔开</returns>
private void GetAllNextIndex(int rowindex, GridRowCollection Rows, ref string strIndexs)
{
string index = GetNextIndex(Rows[rowindex], Rows);
if (string.IsNullOrEmpty(index.Trim()))
return;
strIndexs = string.IsNullOrEmpty(strIndexs) ? index : (strIndexs + "," + index);
string[] indexs = index.Split(',');
foreach (string item in indexs)
{
GetAllNextIndex(int.Parse(item), Rows, ref strIndexs);
}
} /// <summary>
/// 点击事件只给有子集的点击事件(扩展)
/// </summary>
private void TreeClick()
{
StringBuilder sbx = new StringBuilder();
foreach (GridRow row in Rows)
{
//有下级菜单才绑定事件
string Nextindex = GetNextIndex(row, Rows);
if (Nextindex != "")
{
string imgid = ClientID + "_tree_icon_" + row.RowIndex;
sbx.Append("$('#" + imgid + "').click(function(){F.customEvent(\"GridTreeClick_" + row.RowIndex + "\");});");
}
}
PageContext.RegisterStartupScript(sbx.ToString());
} // private static string _moveindex;//移除的数据
/// <summary>
/// 移除的数据(扩展)
/// </summary>
public List<string> MoveIndex
{
get
{
object obj = ViewState["MoveIndex"];
return obj == null ? new List<string>() : obj as List<string>;
}
set
{ ViewState["MoveIndex"] = value;
}
} // private static List<string> _RowCollapsed;//展开集合
/// <summary>
/// 展开集合(扩展)
/// </summary>
public List<string> RowCollapsed
{
get
{
object obj = ViewState["RowCollapsed"];
return obj == null ? new List<string>() : obj as List<string>;
}
set
{ ViewState["RowCollapsed"] = value;
}
} /// <summary>
/// 第一次显示数方法(扩展)
/// </summary>
private void ShowTree()
{
//初始化树
if (EnableTree)
{
if (!ExpandAll)
{
List<string> lstMove = new List<string>();
//循环行
foreach (GridRow row in Rows)
{
//得到层级
int lub = GetLevelNub(row, Rows);
if (lub != )
{
//子集删除
if (!lstMove.Contains(row.RowIndex.ToString()))
lstMove.Add(row.RowIndex.ToString());
}
}
//排序(重要) 从大到小排序,不排序会删除1后造成2变成1
lstMove.Sort(delegate(string str1, string str2) { return int.Parse(str2) - int.Parse(str1); });
if (MoveIndex == null || MoveIndex.Count == )
MoveIndex = lstMove;
string strMoveIndex = string.Empty;
foreach (string item in lstMove)
{
strMoveIndex += string.IsNullOrEmpty(strMoveIndex) ? item : ("," + item);
} string js = string.Empty;
if (!string.IsNullOrEmpty(strMoveIndex))
{
//放入缓存记录已经消除的行 js = ""
+ "var store =" + XID + ".getStore();"
+ "var rows = [" + strMoveIndex + "];"
+ "Ext.Array.each(rows, function (rowIndex, index) {"
+ " store.removeAt(rowIndex);"
+ "});"
//刷新行号,(重要)
+ XID + ".view.refresh();"; }
if (!string.IsNullOrEmpty(js))
PageContext.RegisterStartupScript(js);
//绑定树点击事件
TreeClick();
}
else
{
List<string> _RowCollapsed = new List<string>();
//循环行
foreach (GridRow row in Rows)
{
//得到层级
if (!string.IsNullOrEmpty(GetNextIndex(row, Rows)))
{
if (!_RowCollapsed.Contains(row.RowIndex.ToString()))
_RowCollapsed.Add(row.RowIndex.ToString());
}
}
RowCollapsed = _RowCollapsed;
//绑定树点击事件
TreeClick();
}
}
} /// <summary>
/// 点击树事件(扩展)
/// </summary>
/// <param name="treenode">点击的节点(行号)</param>
public void DoTreeClick(string treenode)
{
if (EnableTree)
{ string strIconJs = string.Empty;
StringBuilder sb = new StringBuilder();
string[] strsmove = new string[MoveIndex.Count];
MoveIndex.CopyTo(strsmove);
List<string> _MoveIndex = new List<string>(strsmove);
string[] strscoll = new string[RowCollapsed.Count];
RowCollapsed.CopyTo(strscoll);
List<string> _RowCollapsed = new List<string>(strscoll);
// ShowTree();
//集合
if (_RowCollapsed == null)
{
_RowCollapsed = new List<string>();
}
//每次点击更改集合,移出和新增
if (_RowCollapsed.Contains(treenode))
{
_RowCollapsed.Remove(treenode);
string strids = string.Empty;
GetAllNextIndex(int.Parse(treenode), Rows, ref strids);
if (!string.IsNullOrEmpty(strids.Trim()))
{
string[] ids = strids.Split(',');
foreach (string item in ids)
{
_RowCollapsed.Remove(item);
string imgid = ClientID + "_tree_icon_" + item;
strIconJs += "$(\"#" + imgid + "\").attr(\"src\",\"" + IconHelper.GetResolvedIconUrl(FineUI.Icon.ControlAddBlue) + "\");";
if (!_MoveIndex.Contains(item))
_MoveIndex.Add(item);
}
}
}
else
{
if (!_RowCollapsed.Contains(treenode))
_RowCollapsed.Add(treenode);
string strids = GetNextIndex(Rows[int.Parse(treenode)], Rows);
if (!string.IsNullOrEmpty(strids.Trim()))
{
string[] ids = strids.Split(',');
foreach (string item in ids)
{
_MoveIndex.Remove(item);
}
}
} int PIDindex = FindColumn(TreeDataParentIDField).ColumnIndex;
int IDindex = FindColumn(TreeDataIDField).ColumnIndex; if (_MoveIndex.Count >= )
{
_MoveIndex.Sort(delegate(string str1, string str2) { return int.Parse(str2 == "" ? "" : str2) - int.Parse(str1 == "" ? "" : str1); });
}
string strMoveIndex = string.Empty;
foreach (string ss in _MoveIndex)
{
strMoveIndex += strMoveIndex == "" ? ss : "," + ss;
} RowCollapsed = _RowCollapsed;
MoveIndex = _MoveIndex; if (strMoveIndex != null)
{
string js = ""
//+"F.ready(function(){"
+ "var store =F('" + ClientID + "').getStore();"
+ "var rows = [" + strMoveIndex + "];"
+ "Ext.Array.each(rows, function (rowIndex, index) {"
+ " store.removeAt(rowIndex);"
+ "});"
//+ XID + ".f_loadData();"
+ "F('" + ClientID + "').view.refresh();"; sb.Append("F('" + ClientID + "').f_loadData();");
sb.Append(js); }
sb.Append(strIconJs);
foreach (string item in RowCollapsed)
{
string imgid = ClientID + "_tree_icon_" + item;
sb.Append("$(\"#" + imgid + "\").attr(\"src\",\"" + IconHelper.GetResolvedIconUrl(FineUI.Icon.ControlRemoveBlue) + "\");");
} PageContext.RegisterStartupScript(sb.ToString());
TreeClick();
} }
/// <summary>
/// 循环子集(扩展)
/// </summary>
/// <param name="treeindex"></param>
/// <param name="movelist"></param>
private void DoNextTreeClick(string treeindex, ref List<string> movelist, bool Collapsed)
{
if (EnableTree)
{
StringBuilder sb = new StringBuilder();
int PIDindex = FindColumn(TreeDataParentIDField).ColumnIndex;
int IDindex = FindColumn(TreeDataIDField).ColumnIndex;
//得到下一菜单
string nextindex = GetNextIndex(Rows[Convert.ToInt32(treeindex)], Rows);
if (nextindex != "")
{
string[] s = nextindex.Split(',');
for (int i = ; i < s.Length; i++)
{
GridRow dr = Rows[Convert.ToInt32(s[i])];
string rowindex = dr.RowIndex.ToString();
//展开
if (movelist.Contains(rowindex) && Collapsed)
{
movelist.Remove(rowindex);
}
//收起
if (!Collapsed && !movelist.Contains(rowindex))
{
movelist.Add(rowindex);
}
//展开子集在展开集合中则执行该子集的展开
if (Collapsed && RowCollapsed.Contains(rowindex))
{
DoNextTreeClick(rowindex, ref movelist, true);
}
}
}
}
} /// <summary>
/// 处理自定义事件(扩展)
/// </summary>
/// <param name="e"></param>
public void CheckCustomEventArgs(CustomEventArgs e)
{
if (EnableTree && !string.IsNullOrEmpty(TreeName) && !string.IsNullOrEmpty(TreeDataIDField) && !string.IsNullOrEmpty(TreeDataParentIDField))
{
if (e.EventArgument.IndexOf("GridTreeClick_") >= )
{
string rowindex = e.EventArgument.ToString().Split('_')[];
DoTreeClick(rowindex);
}
}
} #endregion

grid.cs 修改代码

   private void AfterDataBind(int recordCount)
{
#region hzh modify
if (EnableTree && !string.IsNullOrEmpty(TreeName) && !string.IsNullOrEmpty(TreeDataIDField) && !string.IsNullOrEmpty(TreeDataParentIDField))
{
SortTreeRows();
SetValueTree();
ShowTree(); }
#endregion
if (!IsDatabasePaging)
{
// 如果不是数据库分页,则每次DataBind都要更新RecordCount的值
// 数据库分页的话,RecordCount需要用户显式的赋值
RecordCount = recordCount;
} // 在所有行都绑定结束后,需要检查模拟树显示的列,并重新计算当前列的内容(在列内容前加上树分隔符)
// 1.查找需要模拟树显示的列
BaseField simulateTreeColumn = null;
foreach (GridColumn gridColumn in AllColumns)
{
BaseField column = gridColumn as BaseField;
if (column != null && !String.IsNullOrEmpty(column.DataSimulateTreeLevelField))
{
simulateTreeColumn = column;
break;
}
}
#region hzh modify
if (EnableTree)
{
if (!string.IsNullOrEmpty(TreeName))
{
simulateTreeColumn = FindColumn(TreeName) as BaseField;
}
}
#endregion // 2.如果找到这样的列
if (simulateTreeColumn != null)
{
List<SimulateTreeNode> silumateTree = new List<SimulateTreeNode>(); // 存在需要模拟树显示的列
for (int rowIndex = , rowCount = Rows.Count; rowIndex < rowCount; rowIndex++)
{
GridRow row = Rows[rowIndex];
int level = ;
#region hzh modify
if (EnableTree)
{
level = GetLevelNub(row, Rows) - ;
}
else
{
object treeLevelObj = row.GetPropertyValue(simulateTreeColumn.DataSimulateTreeLevelField);
if (treeLevelObj != null && treeLevelObj != DBNull.Value)
{
level = Convert.ToInt32(treeLevelObj);
}
}
#endregion
object content = row.Values[simulateTreeColumn.ColumnIndex]; SimulateTreeNode node = new SimulateTreeNode();
node.Text = content.ToString();
node.Level = level;
node.HasLittleBrother = false;
node.ParentNode = null;
silumateTree.Add(node);
} // 计算树
SimulateTreeHeper treeHelper = new SimulateTreeHeper();
treeHelper.ResolveSimulateTree(silumateTree, true); // 赋值
for (int rowIndex = , rowCount = Rows.Count; rowIndex < rowCount; rowIndex++)
{
Rows[rowIndex].Values[simulateTreeColumn.ColumnIndex] = silumateTree[rowIndex].Text;
}
} }

pagemanager.cs添加代码

   #region hzh modify
/// <summary>
/// 设置treegrid自定义事件
/// </summary>
/// <param name="e"></param>
private void SetCustomEventArgs(CustomEventArgs e)
{
if (!string.IsNullOrEmpty(TreeGridID))
{
Grid grid = ControlUtil.FindControl(TreeGridID) as Grid;
grid.CheckCustomEventArgs(e);
}
}
/// <summary>
/// TreeGridID(扩展)
/// </summary>
[Category(CategoryName.OPTIONS)]
[DefaultValue(null)]
[Description("TreeGridID(扩展)")]
public string TreeGridID
{
get
{
object obj = FState["TreeGridID"];
return obj == null ? "" : obj.ToString();
}
set
{
FState["TreeGridID"] = value;
}
}
#endregion

pagemanager.cs修改代码

    /// <summary>
/// 触发自定义事件
/// </summary>
/// <param name="e">事件参数</param>
protected virtual void OnCustomEvent(CustomEventArgs e)
{
#region hzh modify
SetCustomEventArgs(e);
#endregion
EventHandler<CustomEventArgs> handler = Events[_handlerKey] as EventHandler<CustomEventArgs>;
if (handler != null)
{
handler(this, e);
}
}

测试页面代码

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestPage.aspx.cs" Inherits="FineUI.Examples.TestPage" %>

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<f:PageManager ID="PageManager1" runat="server" TreeGridID="Grid1"/>
<f:Grid EnableCollapse="true" Width="800px" Height="400px" runat="server" DataKeyNames="Id,Name"
ID="Grid1" EnableTree="true" TreeName="name" TreeDataIDField="id" TreeDataParentIDField="topID"
ShowBorder="true" ShowHeader="true" Title="树表格" ExpandAll="false">
<Columns>
<f:RowNumberField />
<f:BoundField ColumnID="name" ExpandUnusedSpace="true" DataField="name" HeaderText="名称">
</f:BoundField>
<f:BoundField ColumnID="id" DataField="id" Width="50px" HeaderText="ID">
</f:BoundField>
<f:BoundField ColumnID="topID" DataField="topID" Width="50px" HeaderText="topID">
</f:BoundField>
<f:BoundField DataField="levelcode" Width="100px" HeaderText="层级编号">
</f:BoundField>
<f:BoundField ColumnID="levelnub" DataField="levelnub" Width="100px" HeaderText="层级数">
</f:BoundField>
<f:BoundField DataField="subitem" Width="100px" HeaderText="是否为子菜单">
</f:BoundField>
<f:BoundField DataField="url" Width="100px" HeaderText="地址">
</f:BoundField>
</Columns>
</f:Grid>
</form>
<script src="./res/js/jquery.min.js"></script>
</body>
</html>
 using System;
using System.Collections.Generic; using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data; namespace FineUI.Examples
{
public partial class TestPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
return;
DataTable dt = new DataTable();
dt.Columns.Add("name", typeof(string));
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("topID", typeof(string));
dt.Columns.Add("levelcode", typeof(string));
dt.Columns.Add("levelnub", typeof(int));
dt.Columns.Add("subitem", typeof(bool));
dt.Columns.Add("url", typeof(string)); DataRow dr1 = dt.NewRow();
dr1[] = "首页";
dr1[] = ;
dr1[] = ;
dr1[] = "";
dr1[] =;
dr1[] = false;
dr1[] = "adfsdfds";
dt.Rows.Add(dr1); DataRow dr2 = dt.NewRow();
dr2[] = "测试页";
dr2[] = ;
dr2[] = ;
dr2[] = "";
dr2[] = ;
dr2[] = false;
dr2[] = "adfsdfds";
dt.Rows.Add(dr2); //==================== DataRow dr11 = dt.NewRow();
dr11[] = "首页下级1";
dr11[] = ;
dr11[] = ;
dr11[] = "";
dr11[] = ;
dr11[] = true;
dr11[] = "adfsdfds";
dt.Rows.Add(dr11); DataRow dr12 = dt.NewRow();
dr12[] = "首页下级2";
dr12[] = ;
dr12[] = ;
dr12[] = "";
dr12[] = ;
dr12[] = true;
dr12[] = "adfsdfds";
dt.Rows.Add(dr12); DataRow dr13 = dt.NewRow();
dr13[] = "首页下级3";
dr13[] = ;
dr13[] = ;
dt.Rows.Add(dr13); //======================== DataRow dr21 = dt.NewRow();
dr21[] = "测试页下级1";
dr21[] = ;
dr21[] = ;
dr21[] = "";
dr21[] = ;
dr21[] = true;
dr21[] = "adfsdfds";
dt.Rows.Add(dr21); DataRow dr22 = dt.NewRow();
dr22[] = "测试页下级2";
dr22[] = ;
dr22[] = ;
dr22[] = "";
dr22[] = ;
dr22[] = true;
dr22[] = "adfsdfds";
dt.Rows.Add(dr22); DataRow dr221 = dt.NewRow();
dr221[] = "测试页下下级1";
dr221[] = ;
dr221[] = ;
dr221[] = "";
dr221[] = ;
dr221[] = true;
dr221[] = "adfsdfds";
dt.Rows.Add(dr221); DataRow dr00 = dt.NewRow();
dr00[] = "00测试";
dr00[] = ;
dr00[] = ;
dr00[] = "";
dr00[] = ;
dr00[] = true;
dr00[] = "adfsdfds";
dt.Rows.Add(dr00); Grid1.DataSource = dt;
Grid1.DataBind();
} }
}

效果图:

FineUI开源版之TreeGrid(修改)