Вложенные повторители и параметры SqlDataSource - PullRequest
6 голосов
/ 29 января 2009

Я использую вложенные повторители для построения таблицы по причинам, которые я не буду здесь обсуждать, но я хочу получить два источника данных: один для повторителя верхнего уровня, который будет соответствовать строкам, и один для повторитель второго уровня, который будет возвращать ячейки в ряду.

Однако мне интересно, могу ли я как-то указать параметр в источнике данных вложенного повторителя, который задает поле в результатах из первого источника данных?

Можно ли установить для параметра значение выражения привязки данных?

Причина, по которой я хочу это сделать, заключается в том, что у меня есть две хранимые процедуры. Когда страница загружена, у меня есть параметр сеанса, который я могу использовать для запуска первой хранимой процедуры, однако для второй хранимой процедуры мне нужно связать значение из каждого экземпляра повторителя верхнего уровня с вызовом второй хранимой процедуры. с другим значением параметра.

Ответы [ 5 ]

4 голосов
/ 28 марта 2014

Я сделал это с помощью HiddenField, чтобы сохранить значение для использования в качестве параметра позже. Получает работу.

<asp:SqlDataSource ... />
<asp:Repeater ...>
    <ItemTemplate>

        <asp:HiddenField ID="txtOuterID" runat="server" Value='<%# Eval("ID") %>' Visible="false" />

        <asp:SqlDataSource ...>
            <SelectParameters>
                <asp:ControlParameter Name="OuterID" Type="Int32" ControlID="txtOuterID" PropertyName="Value" />
            </SelectParameters>
        </asp:SqlDataSource>

        <asp:Repeater ...>

    </ItemTemplate>
</asp:Repeater>
4 голосов
/ 29 января 2009

Я думаю, что лучшим способом было бы обработать событие ItemDataBound внешнего повторителя, Найти внутренний элемент управления DataSource и установить для него SelectParameter.

    void MyOuterRepeater_ItemDataBound(Object sender, RepeaterItemEventArgs e) 
    {
    // Find the Inner DataSource control in this Row.
    SqlDataSource s = (SqlDataSource)e.Item.FindControl("InnerDataSource");

    // Set the SelectParameter for this DataSource control
    // by re-evaluating the field that is to be passed.
    s.SelectParameters["MyParam"].DefaultValue = DataBinder.Eval(e.Item.DataItem, "MyFieldValueToPass").ToString();
    }

Пример использования DataList приведен в кратком обзоре ASP.NET здесь

P.S .: Пожалуйста, ознакомьтесь с ответом Тони, приведенным ниже, для важного исправления приведенного выше фрагмента. Примечательно, что было бы важно проверить ItemType текущего RepeaterItem. Кроме того, это отличная практика - всегда проверять наличие нулей на каждом объекте.

3 голосов
/ 29 января 2009

Ответ Церебра работает, за исключением того, что есть один улов. Вы получите нулевые исключения, если не будете следовать правилам этого вопроса, я думаю:

Как получить доступ к элементу, привязанному к данным во время ItemDataBound?

По сути, я должен проверить, чтобы убедиться, что рассматриваемый элемент является элементом или чередующимся элементом, в противном случае верхние и нижние колонтитулы вызовут проблемы.

Редактировать: я также получил ошибку при попытке использовать FindControl для получения источника данных. FindControl возвратил ноль, поэтому, когда я пошел к источнику данных, я получил второе нулевое исключение. В итоге я просто получил прямой доступ к объекту. В любом случае источник данных объявляется в файле конструктора. Итак, с этим я, наконец, заставил работать вложенные повторители.

// Find the Inner DataSource control in this Row.

if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == 
    ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.EditItem)
{
    CellsDataSource.SelectParameters["testRunID"].DefaultValue = 
        DataBinder.Eval(e.Item.DataItem, "TestRunID").ToString();
}
3 голосов
/ 29 января 2009

Возможно, вы захотите изучить технику, которая уменьшит количество вызовов sproc. Можно вернуть несколько наборов результатов из одной и той же хранимой процедуры. Набор данных .net имеет возможность определять отношения между несколькими таблицами данных, что позволяет легко брать данные в одной таблице и получать все дочерние узлы в другой таблице данных. Пример:

exampleData.Relations.Add(New DataRelation("FOO_RELATION", exampleData.Tables["TABLE_A"].Columns["ID"], exampleData.Tables["TABLE_B"].Columns["PARENT_ID"]));

Тогда из любого datarow в TABLE_A вы можете получить доступ ко всем детям, как это:

DataRow[] childRows = row.GetChildRows("FOO_RELATION");

Это более эффективно, и IMHO также проще. Таким образом, вам не нужно отправлять вызовы sproc в обработчики событий для вашего ретранслятора.

1 голос
/ 29 января 2009

Я думаю, что вызов FindControl возвращает ноль, потому что сначала нужно вызвать FindControl для вложенного повторителя , а затем вызвать FindControl для возвращенного повторителя.

Repeater rpt  = (Repeater)e.Item.FindControl("rptNested");
SqlDataSource s = (SqlDataSource)rpt.FindControl("InnerDataSource");
...