DropDownList零代码绑定XmlDataSource完全详解

DropDownList控件在直接绑定XmlDataSource的时候会出现错误提示,这个问题把我折腾了好几宿都没睡安稳。MSDN上没有对这个问题的详细解答,CSDN上大家的解决办法也都是五花八门。终归离不开一个思路:以DataSet为跳转,先创建本地数据集从XmlDataSource里把数据取出来,再作为DropDownList的数据源进行数据绑定。这种做法不错,但是写代码的时候难免会出错,并且我对这样做的效率深表怀疑。究其根源,DropDownList不能直接绑定XmlDataSource不是VS的Bug,我也是看了国外一个大牛写的文章,才恍然大悟。

首先创建一个名为XMLDataBing的网站,在App_Data下添加新项,VS会自动添加一个数据库项。选择XML文件,如图。XML的内容就随便写一点吧:
这里写图片描述
这里写图片描述

<?xml version="1.0" encoding="utf-8" ?>

<Texts>

  <Text>
    <Name>Text1</Name>
    <Id>1</Id>
  </Text>

  <Text>
    <Name>Text2</Name>
    <Id>2</Id>
  </Text>

  <Text>
    <Name>Text3</Name>
    <Id>2</Id>
  </Text>

</Texts>

这是最简单也是最基本的。现在看Default.aspx的设计视图,拖一个DropDownList、一个XmlDataSource出来。一般人都会顺手写DropDownList的数据绑定:

<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="XmlDataSource1"
    DataTextField='XPath("Name")' DataValueField='XPath("Id")'>
</asp:DropDownList>
<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/App_Data/XMLFile.xml"
    XPath="/Texts/Text">
</asp:XmlDataSource>

然后编译通过,却在IE里很诧异地得到一个错误:

DataBinding:“System.Web.UI.WebControls.XmlDataSourceNodeDescriptor”不包含名为“XPath(“Name”)”的属性。

很醒目!错误说得很清楚,但是查MSDN死活也找不到XmlDataSourceNodeDescriptor的类定义。Google一下,查到Microsoft Online Community Support上某大牛的解释:

System.Web.UI.WebControls.XmlDataSourceNodeDescriptor is an undocumented internal class which functions like a TypeDescriptor. It is used during data binding when the data source is XmlDataSource. Since it is an internal class, we are not having any public document on it.

大意是:System.Web.UI.WebControls.XmlDataSourceNodeDescriptor是一个未归档的内部类,它的工作原理就像TypeDescriptor。它应用在数据源是XmlDataSource的数据绑定时。由于是个内部类,我们还没有任何关于它的公开文档。

不知各位看了是个什么心情,反正我是万念俱灰了。。。。。。

MS把XmlDataSourceNodeDescriptor作为XmlDataSource数据源进行绑定的重要内部类,出很低级的Bug让DropDownList不能直接绑定XmlDataSource的可能性很小,只是我们忽略了什么重要的东西。再回头想想刚才的整个过程,表面上看不出任何问题。我们不妨重新写一个XML文件,作个小改动:

<?xml version="1.0" encoding="utf-8" ?>

<Texts>

  <Text Name="Text1" Id="1" />

  <Text Name="Text2" Id="2" />

  <Text Name="Text3" Id="3" />

</Texts>

在Default.aspx上新加一个XmlDataSource,DropDownList选择数据源时会有明显的变化!数据源选择XmlDataSource2之后DataTextField和DataValueField选项会自动提示选择Name还是Id。注意,这说明DropDownList能正确读取XML文档了!

问题解决了,但原因还没找到。CSDN里有人说直接绑定就OK,显然是用第二种方法写的XML。这两种写法的区别在于

<Text Name="Text1" Id="1" />
中,Name和Id是Text元素的属性,而

<Text>
  <Name>Text1</Name>
  <Id>1</Id>
</Text>

中,Name和Id并非Text元素的属性,而是一个元素节点。当数据绑定时,元素的属性会被提升为XmlDataSourceNodeDescriptor的属性,通过XmlDataSource暴露出来,但这里的元素节点却不会,导致出错。所以最简单的办法,把你的XML按第二种方法写,就可以零代码绑定了!

不过有人跟我一样喜欢犯贱,非得按第一种方法写。其实照样可以成功,只不过要引入一个XLST文件。不多废话,MSDN对XLST的解释如下:

XSL 转换 (XSLT) 样式表(.xslt 或 .xsl 文件)用于将源 XML 文档的内容转换为专门适合于特定用户、媒介或客户端的表现形式。

说白了,XSLT就是XML的模板。XmlDataSource会按照XSLT规定的模板读取并转换XML文档里的数据,而不考虑XML文档里规定的数据结构。在站点上点右键选添加新项,如图会有XLST文件的模板出现。恩,写一下前面例子的XSLT吧:
这里写图片描述

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="Texts">

    <Texts>

      <xsl:apply-templates select="Text"/>

    </Texts>

  </xsl:template>

  <xsl:template match="Text">

    <Text>

      <xsl:attribute name="Name">

        <xsl:value-of select="Name"/>

      </xsl:attribute>

      <xsl:attribute name="Id">

        <xsl:value-of select="Id"/>

      </xsl:attribute>

    </Text>

  </xsl:template>

</xsl:stylesheet>

OK,别忘了在XmlDataSource1里说明使用刚才的XSLT文件

<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/App_Data/XMLFile.xml"
    XPath="/Texts/Text" TransformFile="~/XSLTFile.xsl"></asp:XmlDataSource>

大功告成!现在得到了正确结果,大家不用再失眠了。使用XSLT还能让DataTextField和DataValueField同时绑定多个元素属性,具体方法大家可以自行Google。只有一个可考虑可忽略的问题:按照第一种写法,使用DataList或者其他某些控件时,用XPath是有效的;DropDownList为什么不能用XPath,还得多研究。

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值