0

カスタム構造体のリストを反復処理する Repeater を含むページがあります。ItemTemplate には SqlDataSource にアタッチされた Repeater がありますが、これはかなりむき出しであり、分離コードの構造体からの情報が取り込まれます。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 および外側の 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
}

(選択は、外側のリピーター アイテムごとに 1 回、2 回だけであるべきだと思うのに 4 回ヒットします。)

指定されたパラメーターと組み合わせた最終的な CommandText を取得し、サーバー マネージャーで適切な結果を取得します。ハードコードされたすべてのものを使用して新しい SQLDataSource を作成し、それも正常に機能しました。ハードコーディングされた sqlDataSources をコピーして貼り付けることはできますが、それではプログラミングの多くのポイントが無効になります (今ではこれで完了しているにもかかわらず)。

これはページのライフサイクルに関係していると考えていますが、それが何であるかはわかりません。複数の反復で 1 つのデータソースを使用することは実行可能ですか? これは表示するデータの選択にのみ使用され、他のコマンドには使用されないことに注意してください。したがって、ポストバックについて心配する必要はありません。

(これは StoredProcedure を使用して大幅に簡素化できることを認識しています。ただし、問題のデータベースは別のアプリケーションによって維持されており、データベースが追加されるたびに SP を展開または展開することを確認するのは面倒であり、これはこの種のことをしている唯一のページです。)

4

1 に答える 1

0

私自身の質問に答えてください。

さらにテストした結果、ページのライフサイクルについては正しいことがわかりましたが、理由は間違っていました。外側の Repeater に最初の DataBinding を実行していましたPage_Init。これにより、DataBinding の内部 Repeater が呼び出されますが、StatementDate と AccountIndex でユーザーが入力したデータを取得するにはライフサイクルが早すぎました。これを変更してPage_Loadその問題を修正しました。

次に、複数の RepeaterItems に対して同じ 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();
    } 
}
于 2012-09-28T19:22:23.683 に答える