http://www.cnblogs.com/xxm/archive/2006/11/30/577157.html
好久没有上来写文章了。一个多月了吧。我也足足的写了一个多月的程序了。每天都在无休止的Code,回忆起来。收获还是蛮多的。都是押宝。这次的一个工程造价软件。TreeList
的使用率高达80%,有时候我也怀疑要不要这么夸张,遍地开花。可是一想。没有它还真不行了。我就无休止的对它进行绑定。捕获按键,保存数据,日子就这样子一天天的过了。我的脑袋里只剩下了一堆的控件。
走到了工资预算这一块。出现了公式的编辑,计算,和修改。关天树形节点的计算,早在这个软件开始编制之前,就解决了。我一直没有想到的是。对于各个父子节点的自由的升级降级,上移下移,还有保存节点的位置,花了几天做了一个节点导航的公共类,总算能把各个节点自由的移动了。自认为这一个功能做的比较成功,只要将当前节点传值给一个导航的静态类。如果有业务限制哪些节点不能移动的话。你可以自己定义一个节点生成的类,传递给静态的一个ClassType属性,就能够实现节点的移动和升降级了。并给出了事件,能够在移动时捕获动作,做出相应的处理,写到这里,我自己都感到好奇怪。每次遇到了什么难办的事。我总是把它和Hashtable,ArrayList这些东东拉进来。加上排序接口,重写几个基类方法,问题就解决了。我不知道这是不是算法。从这个意义上来说。我只是知道如何解决了这个问题,但是真的原因,我却不是很了解,我经常自嘲的说。这就是菜鸟,只知道How。却不知道Why。我的博客只是博客园只微不足道的一个,每篇文章最大的访问量充其量也就是70几号人。也许是瞎转转到这儿来的吧。更多的时候。这些文字只是留给我自己看。让自己能够记起在西安的这段苦日子,还有自己曾苦苦思考的每个问题,看到自己的文章,总还是能想起的。扯远了。这次先不贴导航的代码,把一个关键的绑定代码贴上。就我个人来说。它是我的思维的一种突破,前的代码绑定TreeList的方法,都是围着F_ID在打转,为此我向它妥协了好多地方。总有低声下气的感觉,当我走到了要加载升级和降级节点的TreeList这一步的时候,它终于无可奈何了,这种按照NodeID方法生成Node的方法在父节不断改变的情况下变得无效了ID为1的子节点有可能停靠在ID为30的节点下面。如果按照前面的方法来加载,你会发现整个程序死的很难看。你要把程序升级降级搞的很变态的话。二三百个节点操作后。再次加载你可能只能看到一个了。虽然我可以写一个业务类来限制它们的动作,但这样子总是给人很不爽。也曾想过重新生成一次父子节点的ID,几经周折。看到层次深后的复杂性。我放弃了。说实在的我这个比较笨。思考了整整一天的时候。,我才想到从父节点ID入手来绑定列表。当我一气呵成的写完这个方法的时候。,我自己都觉的自己笨了,这么简单的过程,我竟然想了一天。因为有上升和下降节点的过程,所以,在数据库中加入了Index字段,专门保存各节点的父节点中的索引。通过它和父节点一起排序,我们就得到了一个大概的树形结构图了。但是这是会出现小ID停靠在大ID下面的事了。这时HashTable又发挥了作用,。四点了。话不多说。贴代码
1public static void SimpleModeByPid(DataTable Dt,string Fields,TreeList Ti,String TagColumn)
2 {
3 Ti.Nodes.Clear();
4 Hashtable Address=new Hashtable();//记F_ID与NodeID之间的关系
5 string[] FieldList=Fields.Split(",".ToCharArray());
6 Ti.BeginUnboundLoad();
7 if(ParentFieldName==null && ChildFieldName==null)
8 {
9 return;
10 }
11 foreach(DataRow dr in Dt.Rows)//按照给定的字段生成Node的数据
12 {
13 int index=0;
14 Object[] Data=new object[FieldList.Length];
15 foreach(string o in FieldList)
16 {
17 if(o!=TagColumn && Dt.Columns.IndexOf(o)>-1)
18 {
19 string n=dr[o].ToString().Trim();
20 Data[index]=n;
21 }
22 else
23 {
24 Data[index]="";
25 }
26 index++;
27 }
28
29 int Pid=Convert.ToInt32(dr["P_id"]);
30 if(Pid==0)
31 {
32 TreeListNode Node=Ti.AppendNode(Data,null);
33 Node.Tag=dr[TagColumn];
34 int Fid=Convert.ToInt32(dr["F_id"]);
35 if(!Address.ContainsKey(Fid))
36 {
37 Address.Add(Fid,Node.Id);
38 }
39 }
40 else
41 {
42 if(Address.ContainsKey(Pid))
43 {
44 int Fid=Convert.ToInt32(dr["F_id"]);
45 if(!Address.ContainsKey(Fid))
46 {
47 int ParentID=Convert.ToInt32(Address[Pid]);
48 TreeListNode ParentNode=Ti.FindNodeByID(ParentID);
49 TreeListNode Node=Ti.AppendNode(Data,ParentNode);
50 Address.Add(Fid,Node.Id);
51 Node.Tag =dr[TagColumn];
52 }
53 }
54 else
55 {
56 DataRow[] Dr=Dt.Select("F_id="+Pid);
57 if(Dr.Length>0)
58 {
59 DataRow NowDr=Dr[0];
60 int NowPID=Convert.ToInt32(NowDr["P_id"]);
61 if(Address.ContainsKey(NowPID))
62 {
63 int NowParentID=Convert.ToInt32(Address[NowPID]);
64 TreeListNode NowParentNode=Ti.FindNodeByID(NowParentID);
65 if(NowParentNode!=null)
66 {
67 int i=0;
68 Object[] data=new object[FieldList.Length];
69 foreach(string o in FieldList)
70 {
71 if(o!=TagColumn && Dt.Columns.IndexOf(o)>-1)
72 {
73 string n=NowDr[o].ToString().Trim();
74 data[i]=n;
75 }
76 else
77 {
78 data[i]="";
79 }
80 i++;
81 }
82 TreeListNode node=Ti.AppendNode(data,NowParentNode);
83 node.Tag =NowDr[TagColumn];
84 if(!Address.ContainsKey(Pid))Address.Add(Pid,node.Id);
85 TreeListNode node1=Ti.AppendNode(Data,node);
86 node1.Tag=dr[TagColumn];
87 int Fid=Convert.ToInt32(dr["F_id"]);
88 if(Address.ContainsKey(Fid))
89 {
90 Address.Add(Fid,node1.Id);
91 }
92 }
93 }
94
95 }
96 }
97 }
98 }
99 Ti.EndUnboundLoad();
100 }
哈哈。刚好一百行。Dt是DataTabl,是经过P_id和NodeIndex排序过的。FieldList是需要显示的字段,以逗号隔开。TagColumn是说明将哪一列的值放到TreeListNode的Tag属性中去。和我前面所说的导航类结合在一起。工作的挺好的。希望我的文章能给正在或准备使用TreeList的朋友一些帮助,毕竟很多时候,我们需要的不仅仅是控件自动的绑定。