UpdatePanel, повторитель, проблема привязки данных - PullRequest
5 голосов
/ 09 июня 2010

В пользовательском элементе управления у меня есть Repeater внутри UpdatePanel (идентификатор которого отображается внутри ModalPopupExtender. Repeater связан с данными, используя список массивов объектов MyDTO. Для каждого элемента в списке есть две кнопки. При связывании устанавливаются ImageURL и CommandArgument.

Этот код отлично работает в первый раз, но впоследствии CommandArgument ошибается. Похоже, что дисплей обновляется правильно, но DTO нет, и только что удаленный CommandArgument был удален.

Кто-нибудь может заметить какие-либо проблемы с кодом?

Редактировать: я только что добавил CollapsiblePanelExtender в код. Когда я сейчас удаляю элемент и раскрываю панель, элемент, который был ранее удален (и пропал с дисплея), вернулся. Кажется, что повторитель не был правильно восстановлен под капотом.

ASCX

<asp:UpdatePanel ID="ViewDataDetail" runat="server" ChildrenAsTriggers="true">
    <Triggers>
        <asp:PostBackTrigger ControlID="ViewDataCloseButton" />
        <asp:AsyncPostBackTrigger ControlID="DataRepeater" />
    </Triggers>
    <ContentTemplate>
        <table width="100%" id="DataResults">
        <asp:Repeater ID="DataRepeater" runat="server" OnItemCommand="DataRepeater_ItemCommand" OnItemDataBound="DataRepeater_ItemDataBound">
        <HeaderTemplate>
            <tr>
            <th><b>Name</b></th>
            <th><b>&nbsp;</b></th>
            </tr>
        </HeaderTemplate>
            <ItemTemplate>
            <tr>
                <td>
                <b><%#((MyDTO)Container.DataItem).Name%></b>
                </td>
                <td>
                <asp:ImageButton CausesValidation="false" ID="DeleteData" CommandName="Delete" runat="server" />
                <asp:ImageButton CausesValidation="false" ID="RunData" CommandName="Run" runat="server" />
                </td>
            </tr>
            <tr>
                <td colspan="2">
                <table>
                    <tr>
                    <td>Description : </td>
                    <td><%#((MyDTO)Container.DataItem).Description%></td>
                    </tr>
                    <tr>
                    <td>Search Text : </td>
                    <td><%#((MyDTO)Container.DataItem).Text%></td>
                    </tr>
                </table>
                </td>
            </tr>
            </ItemTemplate>
        </asp:Repeater>
        </table>
    </ContentTemplate>
</asp:UpdatePanel>

Code-Behind

    public DeleteData DeleteDataDelegate;
    public RetrieveData PopulateDataDelegate;
    public delegate ArrayList RetrieveData();
    public delegate void DeleteData(String sData);


 protected void Page_Load(object sender, EventArgs e)
    {
        //load the initial data..
        if (!Page.IsPostBack)
        {
            if (PopulateDataDelegate != null)
            {
                this.DataRepeater.DataSource = this.PopulateDataDelegate();
                this.DataRepeater.DataBind();
            }
        }
    }

    protected void DataRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
    {
        if (e.CommandName == "Delete")
        {
            if (DeleteDataDelegate != null)
            {
                DeleteDataDelegate((String)e.CommandArgument);
                BindDataToRepeater();
            }
        }
        else if (e.CommandName == "Run")
        {
            String sRunning = (String)e.CommandArgument;
            this.ViewDataModalPopupExtender.Hide();
        }
    }

    protected void DataRepeater_ItemDataBound(object source, RepeaterItemEventArgs e)
    {
        RepeaterItem item = e.Item;
        if (item != null && item.DataItem != null)
        {
            MyDTO oQuery = (MyDTO)item.DataItem;

            ImageButton oDeleteControl = (ImageButton) item.FindControl("DeleteData");
            ImageButton oRunControl = (ImageButton)item.FindControl("RunData");

            if (oDeleteControl != null && oRunControl !=null)
            {
                oRunControl.ImageUrl = "button_expand.gif";
                oRunControl.CommandArgument = "MyID";
                if (oQuery !=null)
                { 
                  //do something
                }
                oDeleteControl.ImageUrl = "btn_remove.gif";
                oDeleteControl.CommandArgument = "MyID";
            }
        }
    }

    public void BindDataToRepeater()
    {
        this.DataRepeater.DataSource = this.PopulateDataDelegate();
        this.DataRepeater.DataBind();
    }

    public void ShowModal(object sender, EventArgs e)
    {
        BindDataToRepeater();
        this.ViewDataModalPopupExtender.Show();
    }

Ответы [ 3 ]

7 голосов
/ 12 июня 2010

Спасибо, что напомнили мне, почему я перестал использовать элементы управления ASP.NET. Это именно тот тип кошмара, который заставил слишком много проектов идти за рамки бюджета и графика.

Я советую вам подумать о простейшем способе реализации этого. Вы можете попытаться наклониться назад, чтобы заставить это работать по пути ASP.NET или по кратчайшему пути. Все, что вы делаете, это генерируете HTML, это никогда не должно быть таким сложным.

Наиболее вероятной причиной вашей проблемы является то, что ViewState хранится на странице, которая не обновляется при частичной обратной передаче. Таким образом, с каждым изменением в панели обновлений вы отправляете обратно исходное состояние просмотра страницы.

Попробуйте заменить ретранслятор простым циклом for (и не обращайте внимания на тех, кто начинает жаловаться, что вы не должны смешивать разметку и код). Замените свои операторы привязки данных на <%= %>. Это полностью исключает состояние просмотра и должно удалить все удаленные строки из повторного появления.

1 голос
/ 19 января 2012

попробуйте использовать

((IDataItemContainer) Container) .DataItem

вместо "Container.DataItem"

Это сработало для меня.

1 голос
/ 11 июня 2010

После многих дней возни с этим я не нашел правильного решения проблемы, но у него есть работоспособный обходной путь.

CollapsiblePanelExtender настроен на НЕ выполнять обратную передачу автоматически, что устраняет проблемуудаленные данные снова появляются при открытии расширителя.Другая проблема, я полагаю, связана с этим.

Кажется, что ViewState для повторителя не синхронизирован с данными.e.CommandArgument не всегда корректен и, кажется, ссылается на предыдущие данные.Я попытался исправить это, сохранив ArrayList объектов MyDTO в ViewState при открытии модального диалога и используя идентификатор, полученный из e.Item.ItemIndex, чтобы найти правильный элемент для удаления.Это не сработало правильно, ArrayList, извлеченный из ViewState, был не синхронизирован.

Хранение ArrayList в сеансе заставляет все это работать, что наводит меня на мысль, что я делаю что-то в корне неверное или в версии используемого мной набора инструментов есть небольшая ошибка (мывсе еще на VS2005, так что застряли с более старой версией инструментария)

Извинения, если это не имеет смысла, свяжитесь со мной, если вы хотите что-то разъяснить.

...