1.加图标和事件

上次已经通过DataSimulateTreeLevelField属性控制了树节点的显示,不用看也知道就是给指定列数据前面加个图标的HTML

可以在SimulateTreeHeper类里看到实现方法,不多说了,原理就是循环行累加上图片就可以了,注意图片的ID和样式

  /// <summary>
/// 给树赋值
/// </summary>
private void SetValueTree()
{
if (EnableTree)
{
foreach (GridRow row in Rows)
{
//下级行数
string Nextindex = GetNextIndex(row, Rows);
//默认图标
string iconname = "page.png";
//图片ID,点击用,绑定事件
string imgid = ClientID+"_tree_icon_" + row.RowIndex;
//父节点图标
if (Nextindex != "")
{
iconname = "folder.png";
}
//加入图标和ID,注意加过的就不加了
if (row.Values[FindColumn(TreeName).ColumnIndex].ToString().IndexOf(ClientID+"_tree_icon_") < 0)
{
row.Values[FindColumn(TreeName).ColumnIndex] = "<img id=\"" + imgid + "\" src=\"..\\res\\icon\\" + iconname + "\" width=\"16\" height=\"16\" style=\"margin-top:-5px;margin-bottom:-2px;cursor: pointer\"/>" + row.Values[1];
}
}
}
}
/// <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;
}
这里有个方法是得到下级的行号,这是个核心方法。
在AfterDataBind里加上就可以了

下面就是点击方法,用JQ实现的,从后台输出

        /// <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());
}
还是用到了F.customEvent方法回发后台,其实可以用doPostBack方法直接在Grid.cs里执行,但是考虑到会执行其他方法还是给放到页面的cs文件了,
grid_tree.cs
    protected void PageManager1_CustomEvent(object sender, CustomEventArgs e)
{
if (e.EventArgument.IndexOf("GridTreeClick_") >= 0)
{
string rowindex = e.EventArgument.ToString().Split('_')[1];
Grid1.DoTreeClick(rowindex);
}
}
可以看到DoTreeClick就是点击树图标的方法,这个方法 实现收起和展开。
2.实现展开和收起
在DoTreeClick之前先要有第一次加载方法。
首先要先定义一个参数,这个参数记录应该删除的行号,前面已经说是通过删除行实现收起和展开的
        private static string _moveindex;//移除的数据
/// <summary>
/// 移除的数据
/// </summary>
public static string moveindex
{
get { return _moveindex; }
set { _moveindex = value; }
}

可以看到这个参数是static的不会平白消失,FineUI控制属性的Ajax回发是在构造函数里,

 

有兴趣的可以研究下,我还没太懂
先写一个第一次加载的方法,实现绑定了所有数据但只显示第一层根节点。
  /// <summary>
/// 第一次显示数方法
/// </summary>
private void ShowTree()
{
//初始化树
if (EnableTree)
{
List<string> movelist = new List<string>();
//循环行
foreach (GridRow row in Rows)
{
//得到层级
int lub = GetLevelNub(row, Rows);
if (lub != 0)
{
//子集删除
movelist.Add(row.RowIndex.ToString());
}
}
//排序(重要) 从大到小排序,不排序会删除1后造成2变成1
movelist.Sort(delegate(string str1, string str2) { return int.Parse(str2) - int.Parse(str1); });
string MoveRowIndex = "";
foreach (string s in movelist)
{
MoveRowIndex += MoveRowIndex == "" ? s : "," + s;
}
if (MoveRowIndex != null)
{
//放入缓存记录已经消除的行
moveindex = MoveRowIndex;
string js = ""
+ "var store =" + XID + ".getStore();"
+ "var rows = [" + MoveRowIndex + "];"
+ "Ext.Array.each(rows, function (rowIndex, index) {"
+ " store.removeAt(rowIndex);"
+ "});"
//刷新行号,(重要)
+ XID + ".view.refresh();";
PageContext.RegisterStartupScript(js);
}
//绑定树点击事件
TreeClick();
}
}
逻辑就是得到删除的行号,排序,缓存,js实现,注意刷新行号方法和XID的意义。
加上方法TreeClick方法写在了ShowTree里

下面就可以做展开和收起了,再建一个参数记录展开的行号,专业版实例里可以通过属性控制指定列的展开,我控制这个参数可以实现(这个方法没有写只是理论上的...)

  private static List<string> _RowCollapsed;//展开集合
/// <summary>
/// 展开集合
/// </summary>
public static List<string> RowCollapsed
{
get { return _RowCollapsed; }
set { _RowCollapsed = value; }
}

其实这里可以留扣了,逻辑说出来也不复杂,就都一次写出来吧

 /// <summary>
/// 点击树事件
/// </summary>
/// <param name="treenode">点击的节点(行号)</param>
public void DoTreeClick(string treenode)
{
if (EnableTree)
{
StringBuilder sb = new StringBuilder();
List<string> movelist = null;
if (movelist == null)
{
//集合
if (RowCollapsed == null)
{
RowCollapsed = new List<string>();
}
//每次点击更改集合,移出和新增
if (RowCollapsed.Contains(treenode))
{
RowCollapsed.Remove(treenode);
}
else
{
RowCollapsed.Add(treenode);
}
movelist = new List<string>(moveindex.Split(','));
}
int PIDindex = FindColumn(TreeDataParentIDField).ColumnIndex;
int IDindex = FindColumn(TreeDataIDField).ColumnIndex;
//得到下级菜单
string nextindex = GetNextIndex(Rows[Convert.ToInt32(treenode)], Rows);
if (nextindex != "")
{
string[] s = nextindex.Split(',');
for (int i = 0; i < s.Length; i++)
{
GridRow dr = Rows[Convert.ToInt32(s[i])];
string rowindex = dr.RowIndex.ToString();
//收起动作循环子集收起
if (!RowCollapsed.Contains(treenode))
{
movelist.Add(rowindex);
DoNextTreeClick(rowindex, ref movelist, false);
}
//展开循环子集展开
else
{
movelist.Remove(rowindex);
if (RowCollapsed.Contains(rowindex))
{
DoNextTreeClick(rowindex, ref movelist, true);
}
}
}
moveindex = "";
if (movelist.Count >= 2)
{
movelist.Sort(delegate(string str1, string str2) { return int.Parse(str2 == "" ? "0" : str2) - int.Parse(str1 == "" ? "0" : str1); });
}
foreach (string ss in movelist)
{
moveindex += moveindex == "" ? ss : "," + ss;
}
if (moveindex != null)
{
string js = ""
//+"F.ready(function(){"
+ "var store =F('" + ClientID + "').getStore();"
+ "var rows = [" + moveindex + "];"
+ "Ext.Array.each(rows, function (rowIndex, index) {"
+ " store.removeAt(rowIndex);"
+ "});"
//+ XID + ".f_loadData();"
+ "F('" + ClientID + "').view.refresh();";
//+ "});";
//sb.Append(js);
sb.Append("F('" + ClientID + "').f_loadData();");
sb.Append(js);
}
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 = 0; 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);
}
}
}
}
}

就是点击展开子集,这里判断子集已经展开就继续展开子集,收起要收起该子集的所有子集,主要是参数逻辑的计算。至此功能全部实现

下面应该写图标的展开和收起的改变,全部的前台实现,及其他编辑选择锁定列的测试和修改

ASP.NET-FineUI开发实践-13(二)的更多相关文章

  1. FineUI开源版(ASP.Net)开发实践-目录

    点我订阅 目前所有博客的截图,方便离线观看,点图片 FineUI初学手册 下载,实例项目搭建 FineUI初学手册-部分JS整理 部分JS整理 ASP.NET-FineUI开发实践-1 实际开发环境是 ...

  2. FineUI开发实践-目录

    点我订阅 目前所有博客的截图,方便离线观看,点图片 FineUI初学手册 下载,实例项目搭建 FineUI初学手册-部分JS整理 部分JS整理 ASP.NET-FineUI开发实践-1 实际开发环境是 ...

  3. FineUI开发实践

    ASP.NET-FineUI开发实践-7 摘要: 下拉显示grid列表.其实很简单,但是试了很多方法,水平有限,主要是都不好使,还是简单的好使了,分享下.先是看了看网上的,是直接写个了extjs控件类 ...

  4. Xamarin.Android开发实践(二)

    原文:Xamarin.Android开发实践(二) 一.准备 开始学习本教程前必须先完成该教程http://www.cnblogs.com/yaozhenfa/p/xamarin_android_qu ...

  5. 使用ADO实现BLOB数据的存取 -- ADO开发实践之二

    使用ADO实现BLOB数据的存取 -- ADO开发实践之二 http://www.360doc.com/content/11/0113/16/4780948_86256633.shtml 一.前言 在 ...

  6. ASP.NET-FineUI开发实践-16(二)

    实现那还差点,在事件参数里我传了一个boolall选中状态参数,这个参数由前台给的,RowSelect 传的是index 行号,就是改这,通过$符号来分开的, if (commandArgs.Leng ...

  7. ASP.NET-FineUI开发实践-13(一)

    开原版好像是没有gird树,有一个扩展列下的模拟树列,就是不能展开,专业版有,开原版我弄了弄,思路是有,就是不是很好实现.这篇博客直接写出了(一)说明一个肯定是写不完的. FineUI重在封装,改这个 ...

  8. ASP.NET-FineUI开发实践-9(二)

    其实我也不会,老实教人学怕误人子弟,但是抱着毁人不倦的精神还是糊弄糊弄个别小白吧,最起码能加点原创. 下面以表单为例,打开官方项目,版本为FineUI_4.1.1,打开form_compare页,右键 ...

  9. ASP.NET-FineUI开发实践-4(二)

    在网上找了找,实验了一下window弹出和关闭的动画效果分享一下. 接上次的代码 default.js window_tips.animCollapse= true;//打开动画效果 window_t ...

随机推荐

  1. vim技巧:折叠快捷键

    vim技巧:折叠快捷键 以前用的挺熟的,一段时间不用了,快捷键又忘了,不得不重新再看手册,今天专门整理一下,以后查找起来也比较方便. zc 折叠,只折叠最外层的折叠zC 对所在范围内所有嵌套的折叠点进 ...

  2. Tornado 的教材

    Tornado 的教材 作者:杨昆链接:https://www.zhihu.com/question/19707966/answer/12731684来源:知乎著作权归作者所有,转载请联系作者获得授权 ...

  3. C++关于构造函数的深拷贝与浅拷贝

    首先拷贝构造函数的声明方法: 类名::类名(const 类名&) 1.浅拷贝的实现程序: #include "stdafx.h" #include <iostream ...

  4. BZOJ 1823 满汉全席

    Description 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中.由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉全席,而 ...

  5. [BZOJ 1033] [ZJOI2008] 杀蚂蚁antbuster 【模拟!】

    题目链接: BZOJ - 1033 题目分析 模拟!纯粹按照题目描述模拟! 这是一道喜闻乐见的经典模拟题! 我一共写了2遍,Debug 历时2天的所有晚自习 ... 时间超过 8h ... 我真是太弱 ...

  6. Instagram的技术架构

    http://blogread.cn/it/article/5497 Instagram 被 Facebook 以10亿美金收购.团队规模:13 人.而在被Facebook收购前的一个月,整个团队才7 ...

  7. [转]是String,StringBuffer还是StringBuilder?

    原文链接. 相信大家对 String 和 StringBuffer 的区别也已经很了解了,但是估计还是会有很多同志对这两个类的工作原理有些不清楚的地方,今天我在这里重新把这个概念给大家复习一下,顺便牵 ...

  8. Poetize6: Acting Cute

    3042: Acting Cute Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 59  Solved: 36[Submit][Status] Des ...

  9. 「Poetize4」玉蟾宫

    描述 Description 这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda.现在freda要在这里卖萌...它要找 ...

  10. hdu-2586-How far away ?(离线LCA)

    题意: 给定一棵树,每条边都有一定的权值,q次询问,每次询问某两点间的距离. 分析: 这样就可以用LCA来解,首先找到u, v 两点的lca,然后计算一下距离值就可以了. 这里的计算方法是,记下根结点 ...