image今天打算用Asp.Net复合控件技术制作一个服务器端的文件管理控件,基本实现构想如下:

  1. 设置一个属性,通过该属性指定此控件所管理的根目录路径
  2. 递归向下扫描指定的根目录下的所有子目录及文件,用TreeView控件将其显示出来
  3. 使TreeView显示复选框,用以勾选待处理文件,然后做进一步处理(复制、移动、删除)
  4. 在TreeView中单击某项后,可以对其进行重命名操作,也可以指示将勾选的文件复制、移动到所选目录中

TreeView基本效果如下图:

image

在页面上直接堆控件进行了一番测试,基本没有问题,于是就开始着手创建复合控件了,然而却遭遇连番郁闷……

 

RenderContents()的尴尬

首先我老老实实的在CreateChildControls()方法中书写了创建和添加TreeView控件的代码。

然后在RenderContents()方法中开始扫描目录结构、更新到TreeView控件中,然后输出控件,然而却出现了很奇怪的现象:

  1. 已在CreateChildControls()方法中设定了TreeView的ExpandDepth属性为1,也就是说TreeView应当在首次展示时展开一个层级,而实际是一层都没有展开;
  2. 手动展开根节点后,再继续展开其子节点就莫名其妙地又自动合上根节点了……;
  3. 单击任何一项的时候,会回发到服务器,然后就又回到初始状态了……;

对于第一个问题,我猜测是在CreateChildControls()方法到RenderContents()方法之间的某个生命阶段,TreeView控件可能已被视作进行了首次展示,所以这个属性便失效了。

第二个问题完全没有头绪,个人觉得不太符合科学道理,因为这完全是客户端的范畴,未涉及回发服务器,也就肯定不是代码写错了产生的问题吧,有谁有说得通的见解不妨讲给我。

第三个问题开始猜测是因为没有加“if(!Page.IsPostback)”判定,致使在每次加载页面时都重新刷新一遍TreeView控件,导致总回到初始状态,于是我尝试加入了IsPostback判定,结果再测试时发现回发后TreeView(里的所有节点)彻底消失……

 

OnLoad()的尴尬

鉴于上述第一个问题,我决定把这部分主要功能的代码前移到OnLoad()方法中,结果发现在这时候控件还没初始化(CreateChildControls()方法还未执行)……

 

CreateChildControls()的尴尬

我想干脆把主要功能代码直接写在CreateChildControls()方法里得了,让它在构造时就直接读取文件系统结构来更新TreeView,其结果是:

  1. 显示的根目录不是我在代码中为控件属性指定的目录,而是网页所在的目录;
  2. 点击一下触发回发之后,仍然是一切消失……

对于第一个问题,经过断点调试闹明白了,原来在CreateChildControls()方法执行的时候获取的根目录属性值还是空的,也就是说我在控件的HTML代码中赋予此控件的属性值都还未加载。

第二个问题,乃是“if(!Page.IsPostback)”所致,去掉之后就正常了,视图状态在回发时也能完好保存了,而且也没有之前遇到的展开子节点时自动关闭根节点的灵异事件了。

但是第一个问题仍然是很头疼的,这说明在CreateChildControls()中执行主要功能代码还是太早了,该在哪个阶段执行呢?

PS:另外,由于CreateChildControls()方法的执行时间是不确定的,所以很不稳定,官方也不建议在这里书写重要的功能代码。

 

OnPreRender()的尴尬

尝试把主要功能代码转到RenderContents()方法之前的OnPreRender()阶段执行,遇到的问题是视图状态无法保存,回发时回到初始状态,而其他方面则一切正常,恼~

 

LoadViewState()的尴尬

既然问题出在视图状态这里,那么我们在重写LoadViewState()方法中的base.LoadViewState(savedState)代码之前执行主要功能不就OK了吗?

运行一看:什么都没有了……

后来才想起来,在首次加载的时候应当是不执行LoadViewState()方法的,LoadViewState()仅在页面回发时执行。

 

最终解决办法

这就比较明了了,就是在OnPreRender()中加入“if(!Page.IsPostback)”判定,然后执行主要功能代码,然后再在LoadViewState()中base.LoadViewState(savedState)代码之前再执行一次主要功能代码。

这样在首次加载页面时就是在OnPreRender()时段执行主要功能,而在回发页面时就会在LoadViewState()中执行主要功能,这样就同时解决了属性获取、首次展示、视图状态这三个问题。

实在是很尴尬的一系列生命阶段啊-_-#,这个解决办法也自觉有些山寨风,有高人知道能完美搞定上述问题的生命阶段么?

 

下载

本文的XPS版本:http://www.uushare.com/user/icesee/file/3501295

转载此文章时须注明转载自”SkyD(斯克迪亚)开发者博客“,并保留此文章的Url链接

作者信息

昵称
斯克迪亚

查看其所发布的所有文章

总积分
2420
注册时间
(2018年5月4日 19:06)

评论

目前还没有任何评论。

[切换到移动版页面]