测试发现。
数据源控件,(以dropdownlist为例子)
aspx页面给出了数据源id.并且enableviewstate为true ,只会第一次访问的时候绑定数据库.
enableviewstate为false,每次都会访问数据库.
问题:
1.enableviewstate为true 
绑定数据库的方法的执行时间在哪里?是Page_Load()吗?也是(!ispostback)里面吗?2.enableviewstate为false,每次都会访问数据库,
想了下应该不是在Page_Load()里面的.
因为回发的时候会记录提交的选择项.假如访问数据库在Page_Load()中。因为加载回发数据是在Page_Load()之前的。那先加载回发数据,再访问数据库就肯定不会记录提交选中的选择项.所以想知道数据源控件的databind,数据帮定事件是在页面周期的哪个阶段?
最好提供.net 源码.谢谢。

解决方案 »

  1.   

    查了下源代码:数据源控件都继承了 DataBoundControl.
    DataBoundControl有下面一个方法:protected internal override void OnLoad(EventArgs e)
    {
        base.ConfirmInitState();
        this.ConnectToDataSourceView();
        if (((this.Page != null) && !this._pagePreLoadFired) && (this.ViewState["_!DataBound"] == null))
        {
            if (!this.Page.IsPostBack)
            {
                base.RequiresDataBinding = true;
            }
            else if (base.IsViewStateEnabled)
            {
                base.RequiresDataBinding = true;
            }
        }
        base.OnLoad(e);
    }
     
      

  2.   

    首先是基于.aspx文件创建page 对象
    发生init,load事件
    所有其他控件的触发事件。
    数据源控件完成更新。如果有一行被更新了,就触发Updating和Updated事件。
    如果插入了新行,就触发Inserting 和Inserted事件。如果有一行被删除了,就触发Deleting 和Deleted事件。
    触发Page.PreRender事件。
    数据源控件在连接的控件中执行查询和插入。在这一时刻触发Selecting和Selected事件
    页面返回并且将Page对象析构
      

  3.   

    谢谢讲解。
    这个过程我了解,
    但是我解释不了
    带数据源id的dropdownlist的viewstate为false的情况。
    想了下会不会是这样。 
    viewstate为false。所以.net每次都要在它onload的阶段,重新绑定数据。
    在onload之前,因为dropdownlist实现了IPostBackDataHandler的接口,
    接口有2个方法
    之一:bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection)
    客户断下拉数据变化,返回true。在onload阶段之后引发,因为返回true,所以引发
    IPostBackDataHandler接口的另外一个方法
    void IPostBackDataHandler.RaisePostDataChangedEvent();
    难道在这个方法里面把回发过来的新数据绑定上去了?不知道这样解释对不对。
    知道过程的再解释下
      

  4.   

    有这个疑问是因为带datasourceid的数据控件,只要前台写好数据源就可以了。viewstate,都不要考虑真假情况。
    cs文件中都不用考虑!ispostback的问题。但是这样又麻烦,数据源都在前台,不方便修改。在cs文件中后台绑定,又要考虑(!ispostback).
    能不能在后台控件初始话时候。建立一个数据源。给dropdownlist的数据源id赋直。这样,让.net自动去判断是否回发,等其他情况。
      

  5.   

    你提的这种问题,只要自己写个简单的打印测试就可以了,这种问题还是不求人比较好。真正需要问人的是内部的机制,而不是现象。下面这个测试也可以打印事件序列:<%@ Page Language="C#" %><script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            this.ListBox1.Items.Add("Page_Load");
            this.LoadComplete += (s, a) => { this.ListBox1.Items.Add("Page_LoadComplete"); };
            this.PreRender += (s, a) => { this.ListBox1.Items.Add("Page_PreRender"); };
            this.PreRenderComplete += (s, a) =>
            {
                this.ListBox1.Items.Add("Page_PreRenderComplete");
                if (!Flag)
                    this.ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('注意,本次回发并没有执行ObjectDataSource1_Selecting!');",true);
            };
            this.Unload += (s, a) => { this.ListBox1.Items.Add("Page_Unload"); };
        }    protected void ObjectDataSource1_DataBinding(object sender, EventArgs e)
        {
            this.ListBox1.Items.Add("ObjectDataSource1_DataBinding");
        }    protected void ObjectDataSource1_Init(object sender, EventArgs e)
        {
            this.ListBox1.Items.Add("ObjectDataSource1_Init");
        }    protected void ObjectDataSource1_Load(object sender, EventArgs e)
        {
            this.ListBox1.Items.Add("ObjectDataSource1_Load");
        }    protected void ObjectDataSource1_PreRender(object sender, EventArgs e)
        {
            this.ListBox1.Items.Add("ObjectDataSource1_PreRender");
        }    private bool Flag = false;    protected void ObjectDataSource1_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
        {
            this.ListBox1.Items.Add("ObjectDataSource1_Selecting");
            Flag = true;
        }    protected void ObjectDataSource1_Selected(object sender, ObjectDataSourceStatusEventArgs e)
        {
            this.ListBox1.Items.Add("ObjectDataSource1_Selected");
        }    protected void ObjectDataSource1_Unload(object sender, EventArgs e)
        {
            this.ListBox1.Items.Add("ObjectDataSource1_Unload");
        }
    </script><html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title>演示DropdownList数据绑定事件顺序</title>
    </head>
    <body>
        <form id="form1" runat="server">
        <table width="100%">
            <tr>
                <td valign="top">
                    <asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="ObjectDataSource1">
                    </asp:DropDownList>
                    <br />
                    <br />
                    <asp:Label ID="Label1" runat="server" Text="随便输入:"></asp:Label>
                    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                    <asp:Button ID="Button1" runat="server" Text="测试页面Postback" />
                </td>
                <td valign="top">
                    <asp:ListBox ID="ListBox1" runat="server" EnableViewState="false" Rows="10"></asp:ListBox>
                </td>
            </tr>
        </table>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" OnDataBinding="ObjectDataSource1_DataBinding"
            SelectMethod="GetFileNames" TypeName="BLL" OnInit="ObjectDataSource1_Init" OnLoad="ObjectDataSource1_Load"
            OnPreRender="ObjectDataSource1_PreRender" OnSelecting="ObjectDataSource1_Selecting"
            OnSelected="ObjectDataSource1_Selected" OnUnload="ObjectDataSource1_Unload">
        </asp:ObjectDataSource>
        </form>
    </body>
    </html>
    提供数据源所调用的测试数据的方法类:
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;public class BLL
    {
        static public IEnumerable<string> GetFileNames()
        {
            return new DirectoryInfo("c:\\").GetFiles().Select(f => f.Name);
        }
    }
      

  6.   

    你说的所谓“绑定数据”就是指ObjectDataSource1_Selecting事件发生时所对应的情况。所以,我特意给你单独跟踪出来。如果你认为页面回发的时候,每一次都重新绑定数据,就错了!你恰好可以用这类测试来“嘲笑”一些开发人员,因为网上许多所谓的“教程范例”以及大多数没有经验的编程人员都以为页面回发时应该(在page_load时)重新从数据库等地方绑定数据。这种绑定数据做法,不但偶尔会导致错误(因为当你的数据库内容变化了的时候,出来的ListView等复杂一些的控件就会发现内部字段的结构会发生错误,程序会出错),而且因为总是重新读取数据库还带来性能极其低下。
      

  7.   

    如果你使用数据源控件,相比手工写很多代码而言,出现那种以为需要在page_load中重新绑定数据源的比较可笑的流程控制问题的机会比较小。因为那些数据源控件是经过许多人锤炼过的比较清晰合理的架构,可以使你少写走很多垃圾代码。
      

  8.   

    而且回答你的问题,你可以从测试程序输出中看到,绑定数据是在页面的PreRender和PreRenderComplete之间完成的,根本不是page_load中完成的。要非常重视这个问题,或许你可以因这个问题而开始在很多方面都深入一些asp.net机制去学习。
      

  9.   

    sp123请进来.
    我测试发现,DropDownList1 的EnableViewState="flase"后。
    确实每次都执行了ObjectDataSource1_Selecting.你可以在c盘加入一个文件.再回发.发现下拉数据肯定变了。
    而且每次都是执行Selecting是在 load 之前.而不是EnableViewState="flase"情况下,回发时Selecting是在prerender之后.所以EnableViewState="flase",Selecting.是load之前,也应该是得到最新客户端的回发数据并更新之前.
      

  10.   

    你没有把DropDownList1 的EnableViewState改为flase.
    你改下试试.