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. SSH config

    add  a file named 'config' , place in folder .ssh then you can use  "ssh yourname "quickly ...

  2. Unity各平台路径总结

    路径是Unity开发中令人头疼的一个问题,根据我的开发经验,现将开发中遇到的路径问题总结如下: 1. 如何读取Application.streamingAssetsPath下的文件? Edit.iOS ...

  3. codeforces B. Prison Transfer

    题意:输入n,t,c,再输入n个数,然后问有多少个连续区间内的最大值小于等于t; #include <cstdio> #include <cstring> #include & ...

  4. If one session has a shared or exclusive lock on record R in an index, another session cannot insert

    If one session has a shared or exclusive lock on record R in an index, another session cannot insert ...

  5. 【转】[Java] HashMap使用的示例

    原文网址:http://kings11347.blog.163.com/blog/static/56047032201212895416436/ import java.util.HashMap; i ...

  6. HDOJ 3466 Proud Merchants

    Problem Description Recently, iSea went to an ancient country. For such a long time, it was the most ...

  7. HDOJ 2056 Rectangles

    Problem Description Given two rectangles and the coordinates of two points on the diagonals of each ...

  8. POJ 3280 Cheapest Palindrome(水题)

    题意:给定一个完全由小写字母组成的字符串s,对每个字母比如x(或a,b,c...z),在字符串中添加或者删除它分别需要花费c1['x']和c2['x']的代价,问将给定字符串变成回文串所需要的最少代价 ...

  9. java中的代理

    package cn.itcast.day3; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHan ...

  10. Java并发编程:线程间通信wait、notify

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...