Repeater-in-Repeater SqlDataSource上的编程选择

时间:2012-09-28 03:57:08

标签: asp.net dynamic repeater sqldatasource

我有一个带有Repeater的页面,它遍历一个自定义结构的List。 ItemTemplate有一个附加到SqlDataSource的Repeater,它非常简单,并且将填充来自代码隐藏中struct的信息,其中WHERE子句的不同之处仅在于将<更改为>。 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和选择以及外部Repeater的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
}

(当我认为它应该只有两个时,选择被击中四次,每个外部中继器项目一次。)

我将最终的CommandText与给定的参数结合起来并在服务器管理器中获得正确的结果,我甚至创建了一个新的SQLDataSource,其中包含所有硬编码的内容,并且工作正常。虽然我可以使用硬编码的sqlDataSources进行复制粘贴,但这会破坏很多编程点(尽管我现在已经完成了这一点。)

我的想法是,这与页面生命周期有关,但我无法弄清楚它会是什么。在多次迭代中使用一个数据源是否可行?请注意,这仅用于选择要显示的数据,而不是用于任何其他命令,因此我不需要担心回发。

(我意识到使用StoredProcedure可以大大简化这一点;但是,有问题的数据库是由另一个应用程序维护的,每当添加数据库时部署或确保部署SP会很烦人,这是唯一一个做这种事情的网页。)

1 个答案:

答案 0 :(得分:0)

回答我自己的问题为什么不呢。

经过进一步测试后发现我对页面生命周期是正确的,但出于错误的原因。我正在Page_Init中对外部Repeater进行初始DataBinding;然后,这将调用内部Repeater进行DataBinding,但是在生命周期中检索用户为StatementDate和AccountIndex输入的数据还为时过早。将此更改为Page_Load修复了该问题。

接下来,我决定假设为多个RepeaterItem使用相同的SqlDataSource对象并更改它不会起作用(虽然我仍然不确定),所以我切换到完全创建和绑定代码隐藏中的SqlDataSource。最后,ASP代码与问题中的相同,减去SqlDataSource,现在代码隐藏如下:

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();
    } 
}