使用 SQL Server 2000 & XML Explicit 从数据库动态填充 Microsoft Internet Explorer TreeView Web 控件






4.68/5 (28投票s)
如何使用 SQLXML 和 Explicit 模式动态构建 Internet Explorer TreeView Web 控件节点列表。
引言
Microsoft 提供了 Internet Explorer Web 控件,这些控件默认未包含在框架中。该程序集包含多个控件,其中一个是本文讨论的 TreeView
控件。我将不讨论如何使用该控件,除了使用 SQL Server 的“显式模式”动态加载节点,并设置每个节点的 NavigateUrl
属性以调用 JavaScript 函数。我也不会深入讨论 SQLXML,因为它远远超出了本文的范围。我确实提供了一些关于该主题的进一步信息的链接。我将在未来的文章“SQLXML 数据绑定”中更深入地讨论 SQLXML。有关 TreeView
控件的进一步编程,请参阅 Microsoft 文档。
在哪里可以找到 IE Web 控件下载
虽然将 XML 文档绑定到 TreeView
控件非常方便,但我经常需要即时完成此操作,以适应 TreeView
底层数据结构的动态更改,正如当前业务模型所要求的。实现此动态输出的一种方法是使用 SQL Server 内置的 XML 支持,并结合 TreeView
控件的 TreeNodeSrc
属性。例如,最近我需要为帮助台操作员提供一个已知且常用的分层诊断路径,以便在服务客户时进行选择。输出大致如下:
编写返回 XML 的查询
SQL Server 2000 提供了出色的 XML 支持,通过 explicit
、Auto
和 Raw
等“模式”从 SQL 查询中输出 XML。我们的示例需要使用 explicit
模式来生成 MS 称为通用表的格式,该格式将为我们提供所需的输出。有关从 TSQL 查询返回 XML 的更多信息,请参阅:SQL Server Books on Line 索引,关键字 XML, EXPLICIT,或
我选择在数据库中使用单个自反表以递归方式表示数据来存储分层结构。每一行 fldDiagnosisParentId
都引用另一行 fldDiagnosisId
,但 fldTierNumber
等于 1
的行除外。运行随附的下载 SQLXML 文件来生成此表并填充数据。
运行随附的下载 SQLXML 文件来生成此表并填充数据。
接下来,我们需要一个查询来生成所需的输出。
create procedure spReflexiveNodesText
as
select
1 as Tag,
0 as Parent,
null as [TREENODES!1!text],
null as [treenode!2!text],
null as [treenode!2!NavigateUrl],
null as [treenode!3!text],
null as [treenode!3!NavigateUrl],
null as [treenode!4!text],
null as [treenode!4!NavigateUrl]
union
all
select
2 as Tag,
1 as Parent,
null,
fldDiagnosisLabel as [treenode!2!text],
'Javascript:FillBox("' +
cast(fldDiagnosisId as varchar(10)) + '")'
as [treenode!2!NavigateUrl],
null as [treenode!3!text],
null as [treenode!3!NavigateUrl],
null as [treenode!4!text],
null as [treenode!4!NavigateUrl]
from
tblDiagnosis
where
fldTierNumber = 1
union
all
select
3 as Tag,
2 as Parent,
null,
t1.fldDiagnosisLabel,
'Javascript:FillBox("' + cast(t1.fldDiagnosisId as varchar(10)) + '")',
t2.fldDiagnosisLabel as [treenode!3!text],
'Javascript:FillBox("' +
cast(t2.fldDiagnosisId as varchar(10)) + '")'
as [treenode!3!NavigateUrl],
null,
null
from
tblDiagnosis as t1
inner join
tblDiagnosis as t2
on
t1.fldDiagnosisId = t2.fldDiagnosisParentId
where
t1.fldTierNumber = 1
and
t2.fldTierNumber = 2
union
all
select
4 as Tag,
3 as Parent,
null,
t1.fldDiagnosisLabel,
'Javascript:FillBox("' + cast(t1.fldDiagnosisId as varchar(10)) + '")',
t2.fldDiagnosisLabel,
'Javascript:FillBox("' + cast(t2.fldDiagnosisId as varchar(10)) + '")',
t3.fldDiagnosisLabel as [treenode!4!text],
'Javascript:FillBox("' +
cast(t3.fldDiagnosisId as varchar(10)) + '")'
as [treenode!4!NavigateUrl]
from
tblDiagnosis as t1
inner join
tblDiagnosis as t2
on
t1.fldDiagnosisId = t2.fldDiagnosisParentId
inner join
tblDiagnosis as t3
on
t2.fldDiagnosisId = t3.fldDiagnosisParentId
where
t1.fldTierNumber = 1
and
t2.fldTierNumber = 2
and
t3.fldTierNumber = 3
order by
[TREENODES!1!text],
[treenode!2!text],
[treenode!3!text],
[treenode!4!text]
for
xml explicit
如果您在查询分析器中运行此查询并删除 for xml explicit
指令,您将获得 MS 所称的通用表输出(这对于调试可能很有用)。如果您运行带有 for xml explicit
指令的查询,输出将是一个长 XML 字符串
,如下列表所示。此输出突出显示了一个事实:在此实例中,我们的查询正在生成 TreeView
控件所需的 XML 结构,并利用了 treenode
元素的 NavigateUrl
属性,该属性将调用包含 TreeView
的页面中的 JavaScript 函数。
<TREENODES>
<treenode text="Modem" NavigateUrl="Javascript:FillBox("3")">
<treenode text="Cable" NavigateUrl="Javascript:FillBox("7")">
<treenode text="Broken" NavigateUrl="Javascript:FillBox("11")"/>
</treenode>
</treenode>
<treenode text="Monitor" NavigateUrl="Javascript:FillBox("4")">
<treenode text="Fuzzy" NavigateUrl="Javascript:FillBox("8")">
<treenode text="Driver" NavigateUrl="Javascript:FillBox("12")"/>
</treenode>
</treenode>
<treenode text="PC" NavigateUrl="Javascript:FillBox("1")">
<treenode text="Ram" NavigateUrl="Javascript:FillBox("5")">
<treenode text="Faulty" NavigateUrl="Javascript:FillBox("9")"/>
</treenode>
</treenode>
<treenode text="Printer" NavigateUrl="Javascript:FillBox("2")">
<treenode text="Cartridges" NavigateUrl="Javascript:FillBox("6")">
<treenode text="Empty" NavigateUrl="Javascript:FillBox("10")"/>
</treenode></treenode>
</TREENODES>
注意:所需的自连接次数取决于层级级别数,这并不完全是动态的,这意味着如果您向表中添加一个层级,则需要更改查询。这可以通过先查找表中找到的 max()
层级值,然后在 string
中构建 SQL 语句,然后使用 sp_executesql
系统存储过程执行其中的语句来解决。Union
查询中的第一个 select
语句是必需的,以提供根节点“TREENODES
”,这是 TreeView
控件所必需的。每个 treenode
元素的 text 属性提供了 TreeView
节点各自的显示标签,而 NaviateUrl
通常用于导航到另一个 HTTP 位置,或在此实例中将控件传递给 JavaScript 函数以进行进一步处理。
有关 SQL Server 2000 中可用 XML 模式的更多信息,请查看 此链接。此链接提供了由 Graeme Malcolm 撰写、MS Press 出版的书籍“Programming Microsoft® SQL Server™ 2000 with XML”的示例章节。
设置 SQL Server 以通过 URL 访问
使查询为我们工作的下一步是设置一个 SQL Server 2000 虚拟目录,这将允许我们使用 URL string
调用存储过程。安装 SQL Server 时,它应该会在其开始菜单文件夹中配置一个名为“配置 IIS 中的 SQL XML 支持”的菜单项。
完成后,您将能够通过 URL 访问 Internet Explorer 中的存储过程:https:///TreeSqlXml?sql=execute+spReflexiveNodesText。
有关如何设置虚拟目录的更多信息,请参阅:SQL Server Books 或尝试 MSDN 网站。
有关如何设置 SQL Server 以使用 URL 字符串查询数据库的更多信息,请参阅:Books on Line 并使用索引关键字“XML, 在 URL 上执行存储过程”或尝试 MSDN 网站。
ASPX 页面的 HTML 代码。
<!DOCTYPEHTMLPUBLIC"-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>ReflexiveTreeNodes</title>
<metaname="GENERATOR"Content="Microsoft Visual Studio 7.0">
<metaname="CODE_LANGUAGE"Content="C#">
<metaname="vs_defaultClientScript" content="JavaScript">
<metaname="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
<scriptlanguage="javascript">
<!--
/* The Function specified in the output
of the stored procedure
SEE the NavigateUrl attribute
Of each treenode element */
function FillBox(val)
{
alert(val);
}
//-->
</script>
</HEAD>
<bodyMS_POSITIONING="GridLayout">
<formid="ReflexiveTreeNodes" method="post" runat="server">
<!--Note the URL string used as the value of the TreeNodeSrc -->
<iewc:TreeViewid="TreeView1"
style="Z-INDEX: 101; LEFT: 6px; POSITION: absolute; TOP: 8px"
runat="server"
TreeNodeSrc="https:///TreeSqlXml?sql=execute+spReflexiveNodesText">
</iewc:TreeView>
</form>
</body>
</HTML>
注意:请记住在项目中引用 Microsoft.Web.UI.WebControls.dll,并将存储过程的 URL 作为 TreeView
标签的 TreeNodeSrc
属性的值。
缓存
根据底层数据库表的预期更改频率以及是否将任何参数从应用程序传递到存储过程,为您的页面选择最合适的缓存策略。请记住,存储过程将根据请求的数据是否已缓存来从数据库或缓存中获取数据。
最后
还值得一提的是,TreeView
控件也可以通过将 XML 文件的完全限定路径传递给 TreeNodeSrc
属性来填充。
TreeNodeSrc="myTreeViewFile.xml"