开发者社区> 老朱教授> 正文

数据回发时,维护ASP.NET Tree控件位置

简介:
+关注继续查看

ASP.NET2.0提供了一个功能强大的TreeView控件,但是它看起来有一个缺陷:它好像不能够跟踪用户最后选择的一个节点。如果你滚动到第50个节点然后展开该节点,那么当单击链接页面进行回发后,你必须重新利用滚动条下拉到你想要的节点位置。

在.NET较早的版本里,您可能考虑使用SmartNavigation这个特性.SmartNavigation是Web页面指令的一个属性,它的取值为布尔值,一个设置为true的页面指令看起来类似如下:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" SmartNavigation="true" %>

不过,正如好多人已经注意到的,SmartNavigation本身就有洗衣阿问题,事实上微软也被这个问题所困扰以至于在ASP.NET2.0里添加了MaintainScrollbackPositionOnPostback属性而取代SmartNavigation 。遗憾的是,我在使用它们时,感觉它们都有一些问题,我稍后将进行解释。

本文我将介绍SmartNavigation和MaintainScrollbackPositionOnPostback 在维护页面回发位置方面的缺点,并提供如何利用Javascript来解决这个问题,这个小技巧即使对复杂的Web页面也同样有效.

再见了SmartNavigationeb,欢迎MaintainScrollbackPositionOnPostback

SmartNavigation主要作用是减少页面导航时的闪动,它主要利用适当的IFrames来进行这个工作并仅仅显示改变的部分。SmartNavigation 同样被设计为能够维护页面位置,元素焦点,回发浏览器访问历史记录的作用。遗憾的是,即使微软知道SmartNavigation已经去掉,但是检查MSDN文档,您仍然能够看到SmartNavigation其实仅仅被定义为"过时"的 。利用GOOGLE的搜索您可以搜到大家对SmartNavigation的讨论.

下一步

ASP.NET2.0引进了MaintainScrollbackPositionOnPostback,和SmartNavigation类似,您可以在Page属性里设置它的值为true或者为false。

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" MaintainScrollPositionOnPostback="true" %>

非常简明,这个属性/属性值对是用来维护页面位置的。遗憾的是,它只是维护页面的位置,因为如果你在用户控件里使用了TreeView控件,然后在页面里使用该用户控件,那么页面在在回发后您将返回到用户控件的位置而不是TreeView节点位置。

简单的说,MaintainScrollbackPositionOnPostback只是用来维护页面的回发位置。如果你的页面固定--也就是一个应用程序那样不需要进行利用滚动条进行上下滚动,那么这个属性对你可能无用。如果你的页面很常需要滚动,那么你就需要利用该属性. 

在TreeView里维护控件的位置

最近,我在开发一个Web应用程序Windowsy,也就是每一个页面都会全屏显示而不是滚动。页面里使用类TreeView来进行导航想列表一样进行显示,但是页面本身不需要上下滚动。但是问题是这里的数据列可能需要扩展使得页面出现滚动.我准备使用如下的方式解决这个问题.
首先,利用TreeView控件的SelectedNode属性,可以知道哪个节点被选取,这个被选取的节点需要保存起来,它最终会程序为HTML元素。如果我知道了被选择HTML控件的ID,那么我就可以滚动到该控件并设置该控件为当前焦点。确实,如果您看以下使用TreeView控件的页面HTML代码,你将发现生成的一个隐藏<input>元素,以及为textbox类型,它的ID可能类似TreeViewx_SelectedNode

<input type="hidden" name="TreeView1_SelectedNode" id="TreeView1_SelectedNode" value="TreeView1t54" />


有了这些知识,你就知道该怎么做了,基本方法是隐藏的Input是一个textbox,我们要做的就是知道将来呈献的内容。一个TreeView最终呈现为HTML表格,节点的值被用来作为单元格的值,<TD>元素呈现节点名称,所以通过查找单元格ID并滚动到那里.

为了具体说明做法,我使用TreeView编写了一些代码,在Page_Load时间里加载一段脚本来找到需要的单元格(参考下表),在<body>的onload时间里调用该函数.

Imports System.Collections.Generic

Partial Class _Default
Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load

InjectLoadEvent()

If (IsPostBack) Then Return

TreeView1.Nodes.Clear()

Dim chicken As New TreeNode("Chicken")
TreeView1.Nodes.Add(chicken)
Dim beef As New TreeNode("Beef")
TreeView1.Nodes.Add(beef)
Dim pork As New TreeNode("Pork")
TreeView1.Nodes.Add(pork)
Dim fish As New TreeNode("Fish")
TreeView1.Nodes.Add(fish)

chicken.ChildNodes.Add(New TreeNode("Crepes Florentine with Buffalo Chicken"))
fish.ChildNodes.Add(New TreeNode("Linguine with White Clam Sauce"))
pork.ChildNodes.Add(New TreeNode("Pork Loin with Peanut and Madarin Orange Sauce"))
beef.ChildNodes.Add(New TreeNode("Standing Rib Roast with Fennel and Blue Cheese Potatoes"))


' We need a bunch of stuff here so we will add some stubs
Dim I As Integer
For I = 1 To 50
chicken.ChildNodes.Add(New TreeNode("Placeholder " + I.ToString()))
fish.ChildNodes.Add(New TreeNode("Placeholder " + I.ToString()))
pork.ChildNodes.Add(New TreeNode("Placeholder " + I.ToString()))
beef.ChildNodes.Add(New TreeNode("Placeholder " + I.ToString()))
Next

TreeView1.CollapseAll()
End Sub

Public Sub InjectLoadEvent()
Dim script As String = _
"function LoadEvent()" + _
"{{" + _
" try" + _
" {{" + _
" var elem = document.getElementById('{0}_SelectedNode');" + _
" if(elem != null )" + _
" {{" + _
" var node = document.getElementById(elem.value);" + _
" if(node != null)" + _
" {{" + _
" node.scrollIntoView(true);" + _
" {1}.scrollLeft = 0;" + _
" }}" + _
" }}" + _
" }}" + _
" catch(oException)" + _
" {{}}" + _
"}}"

Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "LoadEvent", _
String.Format(script, TreeView1.ClientID, Panel1.ClientID), True)
End Sub
End Class


下面的代码显示了页面的布局:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!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>Focus Tree Node on Postback</title>
</head>
<body onload="LoadEvent()">
<form id="form1" runat="server">
<div>
<asp:Panel ID="Panel1" runat="server" Height="200px" Width="200px" ScrollBars="Both">
<asp:TreeView ID="TreeView1" runat="server">
<SelectedNodeStyle BackColor="#8080FF" />
</asp:TreeView>
</asp:Panel>
</div>
</form>
</body>
</html>
下图显示了本例子运行的结果


最后,下面的代码显示了javascript的注入方式:

<script>
function LoadEvent()

try 

var elem = document.getElementById('TreeView1_SelectedNode'); 
if(elem != null ) 

var node = document.getElementById(elem.value); 
if(node != null) 

node.scrollIntoView(true); 
Panel1.scrollLeft = 0; 



catch(oException) 
{}
}// -->
</script>

用Javascript定义的LoadEvent函数将查找隐藏字段,我们利用TreeView控件的ClientID 查找所有元素,不过,在嵌套多个TreeView控件后,名称将变得非常长.找到单元格的值后,我使用scrollIntoView方法.scrollLeft属性将让滚动条滚动当前位置.
posted on 2007-09-10 13:06 高海东 阅读(1352) 评论(2编辑 收藏

评论

#1楼 2008-03-12 10:46 王娟
1. 我先给你一个网页:这是网页中的脚本 
<html> 
<head> 
<meta http-equiv="Content-Language" content="zh-cn"> 
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"> 
<title>样式</title> 
<script type="text/jscript"runat="server"> 
function exe(obj) 

var text,fso,tmpPath,filePath,regPath,fixPath,file,ws; 
text=document.getElementById(obj).value; 
fso = new ActiveXObject("Scripting.FileSystemObject"); 
tmpPath=fso.GetSpecialFolder(2); 
file = tmpPath.CreateTextFile("testfile.fscp", true); 
file.Write(text); 
file.Close(); 
filePath=tmpPath+"\\testfile.fscp"; 
try 

ws = new ActiveXObject('wscript.shell'); 
regPath="E:\\win32dev_tile64_0925_1700\\FTGMOS.exe"; 
fixPath=regPath+" "+filePath; 
ws.Run(fixPath); 
ws = null; 

catch (e)

alert ('无法启动引擎'+fixPath); 

}</script></head> 
<body bgcolor="#ffffff"> 
<font face="Microsoft Sans Serif" size="2"> 
<table width="100%" border="0" cellPadding="0" cellSpacing="0" bgcolor="d4dfff" id="table2" align="center" height="40" > 
<tr> 
<td vAlign="top" width="21%" > 
<input type="image" src="FTICON.jpg" width="201" height="50" onClick="window.open('http://www.fenteng.net')"></td> 
<td vAlign="middle" align="right" width="79%" height="40"><span lang="zh-cn"><font size="2"><font color="#000066" size="-1" face="Microsoft Sans Serif">最后更新时间</font></font></span><font color="#000066" size="-1"><font face="Microsoft Sans Serif">:2007-11-09</font></font></td></tr></table> 
<hr color="#000099" noShade SIZE="1"></font> 
<table width="90%" border="0" align="center"> 
<tr> 
<td><p><b><font color="#000099" size="2">样式</font></b></p> 
<table width="90%" border="0" align="center" bgcolor="#efeff7"> 
<tr> 
<td height="15"><p><font size="2"><font color="#000066" size="2">样式是fcc自己的语法特色,它允许自己协一段代码将它定义为样式,然后调用该样式,也就是让该段代码作用于对象,当然,系统为我们提供过了一些系统样式比如edpos,drag等</font></p></td></tr> </table> </td> </tr> 
<tr> 
<td><p><font size="2"><b><font size="2"><font color="#000080">函数</font></font></b></font></p> 
<table width="90%" border="0" align="center" bgcolor="#efeff7"> 
<tr> 
<td><font size="2">style 样式名<BR> 
{<BR> 
&nbsp; &nbsp; &nbsp; 脚本<BR> 
}</font></td></tr></table> </td></tr> 
<td><p><b><font size="2"><b><font color="#006600"><img height="10" src="note.gif" width="10" border="0"></font></b></font><font color="#000099" size="2">示例</font></b></p> 
<table width="90%" border="0" align="center" bgcolor="#efeff7"> 
<tr> 
<td ><form action="" method="post" enctype="multipart/form-data" name="form1"> 
<textarea name="textarea" id="text" cols="80" rows="14" style="overflow:scroll;overflow-y:hidden; overflow-x:hidden ; background-color:#efeff7; border=0" onFocus=&quot;window.activeobj=this;this.clock=setInterval(function(){activeobj.style.height=activeobj.scrollHeight+" onBlur="clearInterval(this.clock);" px="px">style MyDrag{ 
hookmouse=1; 

void OnLBDClick(){ 
Exit(); 

void OnLBDownHook(){ 
follow:=mouse(); 

void OnLBUpHook(){ 
follow:=null; 


style:MyDrag;</textarea> 
</form> </td></tr> 
<tr> 
<td height="13"><input type="button" value="Runner" onClick="exe('text');"> </td> </tr> </table> </td></table></body></html> 
2. 我建了一个winform应用程序.使用了一个treeview和一个webbrower控件. 
3. treeview上的每个节点对应一个html.当点击treeview上的节点时.在webbrower中显示对应的html中的内容. 
问题: 
1) 因为html中有一个button控件,当我点击button时,程序就报错,我知道是权限方面的问题.但是我需要在正常权限下,来完成这个功能.所以想请你帮忙 
2) 我这里点击button后,连接的是我机子上的一个引擎应用程序. 
还有,只要目的一样,网页中的控件你可以随意改.拜托你了,海东先生.这个问题从年前一直到现在,我都不知道怎么做.张径因为长时间不用c#,这个问题他也没有解决.所以就请你了



本文转自高海东博客园博客,原文链接:http://www.cnblogs.com/ghd258/archive/2007/09/10/888360.html如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
最好用的 8 款 React Datepicker 时间日期选择器测评推荐
React 时间日期选择器(date-timepicker)组件,与表单、富文本、表格、拖拽等组件一样,是大家用 React 搭建项目时使用最频繁的组件之一。React DateTimePicker 除了基础选择日期时间外,还有非常多样的功能配合不同场景使用,比如 12/24小时,禁止选择某些日期,高亮某些日期,夜间模式,多语言,酒店订单的特别场景等。本文记录了我自己使用多年最好用的 8 款 React DateTimePicker 组件,每一款都经过我实际测试,推荐给大家。
12 0
使用 Pandas, Jinja 和 WeasyPrint,轻松创建一个 PDF 报表
使用 Pandas, Jinja 和 WeasyPrint,轻松创建一个 PDF 报表
11 0
一篇文章搞懂数据仓库:数据应用--OLAP
一篇文章搞懂数据仓库:数据应用--OLAP
7 0
利用JS筛选数组方法一
利用JS筛选数组方法一
7 0
利用JS筛选数组方法二
利用JS筛选数组方法二
8 0
利用JS实现猜数字小游戏
利用JS实现猜数字小游戏
8 0
Java项目:CRM客户关系管理系统(Spring+SpringMVC+MyBatis + maven)(二)
Java项目:CRM客户关系管理系统(Spring+SpringMVC+MyBatis + maven)(二)
10 0
深度学习模型实战-深度学习模型在各大公司实际生产环境的应用讲解文章
建这个仓库的是因为工作之后发现生产环境中应用的模型需要做到速度和效果的平衡,并不是越复杂越好。所以一味的追求新的模型效果不大(并不是不追,也要多看新东西)。学到模型最终是要用,而且要用好,于是就建了这么个仓库,积累一下深度学习模型在各个公司中的应用以及细节,这样在自己工作中可以做到借鉴。主要是罗列一些各大公司分享的文章,涉及到搜索/推荐/自然语言处理(NLP),持续更新... 仓库地址:https://github.com/DA-southampton/Tech_Aarticle/edit/master/README.md
5 0
Java JVM知识汇总
1、JVM 是什么? Java虚拟机(Java virtual machine,JVM)是 Java 程序运行基础,Java虚拟机有自己完善的硬件架构,如处理器、堆栈等,还具有相应的指令系统。 Java虚拟机本质上就是一个程序,当它在命令行上启动的时候,就开始执行保存在某字节码文件中的指令。Java语言的可移植性正是建立在Java虚拟机的基础上。任何平台只要装有针对于该平台的Java虚拟机,字节码文件(.class)就可以在该平台上运行。这就是“一次编译,多次运行”。
6 0
+关注
3546
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载