0

我有一个带有重复器的页面,它遍历自定义结构的列表。ItemTemplate 有一个Repeater 附加到一个相当裸露的SqlDataSource,它将使用代码隐藏中结构的信息填充,其中WHERE 子句的不同之处仅在于将a 更改<为a >。StatementDate 和 AccountIndex 分别是用户填写以定义信息的 TextBox 和 DDL。但是,所有以编程方式设置各种 sqlDataSource 详细信息的尝试都不会返回任何内容(错误或行。)

<asp:Repeater ID="SelectedRepeater" runat="server" onitemdatabound="SelectedRepeater_ItemDataBound">
        <ItemTemplate>
            <asp:Repeater ID="EntryRepeater" DataSourceID="RecordsDataSource" runat="server" OnItemDataBound="EntryRepeater_ItemDataBound">
                <ItemTemplate>
                    <tr>
                        <td>
                            <%# Eval("TrxDate", StandardDate) %>
                            <span class="error"><%# ShowExclamation(Eval("DateCleared")) %></span>
                        </td>
                        <td><%# Eval("Reference")%></td>
                        <td><%# Eval("VendorName")%></td>
                        <td><%# Eval("Memo")%></td>
                        <td class="money"><%# Eval("Amount","{0:n2}")%></td>
                    </tr>
                </ItemTemplate>
            </asp:Repeater>
            <asp:SqlDataSource ConnectionString="<%=ConnectionString(ActiveClient)%>" ProviderName="System.Data.SqlClient" OnSelecting="RecordsDataSource_Selecting" ID="RecordsDataSource" OnDataBinding="RecordsDataSource_DataBinding" runat="server">
                <SelectParameters>
                    <asp:ControlParameter ControlID="StatementDate" DefaultValue="2/2/1900" Name="StatementDate" 
                        PropertyName="Text" />
                    <asp:ControlParameter ControlID="AccountIndex" DefaultValue="" Name="AccountIndex" 
                        PropertyName="SelectedValue" />
                </SelectParameters>
            </asp:SqlDataSource>
        </ItemTemplate>
    </asp:Repeater>

我尝试使用 SqlDataSource 的 DataBinding 和 Selecting 以及外部中继器的 ItemDataBound:

protected void RecordsDataSource_DataBinding(object sender, EventArgs e) {
    _currentCommand = String.Format(_standardSelect, Eval("WhereClause").ToString());
    SqlDataSource sds = sender as SqlDataSource;
    sds.SelectCommandType = SqlDataSourceCommandType.Text;
    sds.SelectCommand = String.Format(_standardSelect, Eval("WhereClause").ToString());
}

protected void SelectedRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) {
    if (IsListItemRow(e.Item)) {
        SqlDataSource sds = (e.Item.FindControl("RecordsDataSource") as SqlDataSource);
        sds.SelectCommand = String.Format(_standardSelect, ((PrintSection)e.Item.DataItem).WhereClause);
        sds.Select(DataSourceSelectArguments.Empty);
    }
}

protected void RecordsDataSource_Selecting(object sender, SqlDataSourceSelectingEventArgs e) {
    e.Command.CommandText = _currentCommand; //set in DataBinding
}

(Selecting is hit four times when I would think it should be only two, once for each outer Repeater item.)

I take the final CommandText combined with the given parameters and get the proper results in Server Manager, I even made a new SQLDataSource with everything hardcoded and that worked fine, too. While I could copy-paste with hard-coded sqlDataSources, that defeats a lot of the point of programming (even though I'd be done with this by now.)

My thinking is that this has to do with the Page Lifecycle, but I can't figure out what it would be. Is it even viable to use one datasource over multiple iterations? Note that this is only used for selecting data to display, not for any other commands, so I don't need to worry about postback.

(I realize that this could be simplified greatly with the use of a StoredProcedure; however, the database in question is maintained by another application, and deploying or making sure that an SP is deployed whenever a database is added would be annoying, and this is the only page doing this kind of thing.)

4

1 回答 1

0

Answer my own question why not.

After further testing it turns out I was right about page Lifecycle, but for the wrong reasons. I was doing the initial DataBinding to the outer Repeater in Page_Init; this would then call the inner Repeater for DataBinding, but it was too early in the Lifecycle to retrieve the data entered by the user for StatementDate and AccountIndex. Changing this to Page_Load fixed that issue.

Next, I decided to work on the assumption that using the same SqlDataSource object for multiple RepeaterItems and changing it was not going to work (though I'm still not sure of this), so I switched to completely creating and binding the SqlDataSource in the codebehind. In the end, the ASP code is the same as in the question, minus the SqlDataSource, and the codebehind is now as follows:

protected void SelectedRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) {
    if (IsListItemRow(e.Item)) { //checks for both Item and AlternateItem
        SqlDataSource sds = new SqlDataSource(ConnectionString(ActiveClient), 
                String.Format(_standardSelect, ((PrintSection)e.Item.DataItem).WhereClause));
        sds.SelectParameters.Add("StatementDate", StatementDate.Text);
        sds.SelectParameters.Add("AccountIndex", AccountIndex.SelectedValue);
        sds.Select(DataSourceSelectArguments.Empty);
        Repeater innerRepeater = (e.Item.FindControl("EntryRepeater") as Repeater);
        innerRepeater.DataSource = sds;
        innerRepeater.DataBind();
    } 
}
于 2012-09-28T19:22:23.683 回答