【问题标题】:UpdatePanel, Repeater, DataBinding ProblemUpdatePanel、Repeater、DataBinding 问题
【发布时间】:2011-03-01 19:41:32
【问题描述】:

在用户控件中,我在 UpdatePanel 内有一个 Repeater(其 ID 显示在 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>

代码隐藏

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

【问题讨论】:

  • ItemDataBound 处理程序中是否缺少代码?在该方法中,您声明了一个 MyDTO 变量 (oQuery),然后永远不要使用它。
  • 对不起,是的,为了简洁起见,我把它剪掉了

标签: asp.net asp.net-ajax .net-2.0 updatepanel repeater


【解决方案1】:

在搞砸了很多天之后,我还没有找到解决问题的合适方法,但确实有一个可行的解决方法。

CollapsiblePanelExtender 设置为不自动回发,这解决了在打开扩展器时重新出现已删除数据的问题。我相信另一个问题是相关的。

Repeater 的 ViewState 似乎与数据不同步。 e.CommandArgument 并不总是正确的,似乎引用了以前的数据。我尝试通过在打开模态对话框时将 MyDTO 对象的 ArrayList 存储在 ViewState 中并使用从 e.Item.ItemIndex 检索到的 ID 来查找要删除的正确元素来修复它。这不能正常工作,从 ViewState 中拉出的 ArrayList 不同步。

在会话中存储 ArrayList 使一切正常,这让我相信我做的事情根本上是错误的,或者我正在使用的工具包版本中有一个细微的错误(我们仍在使用 VS2005所以被旧版本的工具包卡住了)

抱歉,如果这没有任何意义,如果您想澄清任何事情,请与我联系。

【讨论】:

    【解决方案2】:

    感谢您提醒我为什么停止使用 ASP.NET 控件。这正是使太多项目超出预算和进度的噩梦的确切类型。

    我给你的建议是想出最简单的方法来实现它。您可以尝试向后弯腰,以使其以 ASP.NET 方式工作或采用最短路线。 您所做的只是生成 HTML,它应该永远不会那么困难。

    问题的最可能原因是 ViewState 存储在未在部分回发时更新的页面中。因此,随着更新面板中的每一次更改,您将回发页面的初始视图状态。

    尝试用一个简单的 for 循环替换中继器(忽略那些开始抱怨你不应该混合标记和代码的人)。将您的数据绑定语句替换为&lt;%= %&gt;。 这会一起消除视图状态,并且应该删除任何已删除的行以防止重新出现。

    【讨论】:

    • 你说得对,我现在已经不再为这些烦恼了,一切都是 jQuery 和 web 服务。我的生活变得 100% 更轻松,一切都更快地实施..
    【解决方案3】:

    尝试使用

    ((IDataItemContainer)Container).DataItem

    而不是“Container.DataItem”

    它对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多