在 ASP.NET 中,当单击在 asp:Repeater 中呈现的 ascx 控件中的按钮时,会丢失值。

8
我创建了一个asp:Repeater,并通过填充.ascx控件来完成:
protected void Page_Load(object sender, EventArgs e)
{
    Repeater1.DataSource = listOfData;
    Repeater1.DataBind();            
}

我有一个页面:

<uc:Product runat="server"                                             
    ImportantData='<% #Eval("ImportantData") %>'                                               
    id="DetailPanel1" />

Product.ascx.cs 文件中,我有以下代码:

public int ImportantData{ get; set; }
protected void Page_Load(object sender, EventArgs e)
{

}

Product.ascx 中,我有以下内容:
<asp:ImageButton ID="btn_Ok" runat="server" 
     onclick="btn_Ok_Click"  
     ImageUrl="~/image.png" />

当我点击图像按钮时,出现错误:
A critical error has occurred. Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page...

我尝试将第一个代码更改为以下内容:
protected void Page_Load(object sender, EventArgs e)
{
    if(!Page.IsPostBack)
    {
        Repeater1.DataSource = listOfData;
        Repeater1.DataBind();            
    }
    // Repeater1.DataBind(); // and tried to put DataBind() here
}

但是当我点击图像按钮时,ImportantData为空。我在这里做错了什么?

ImportantData 是从哪里获取的?你确定绑定列表中的对象都有它吗? - Wiktor Zychla
你尝试过设置EnableEventValidation="false"吗? - Christos
“我填充.ascx控件的列表”让我感到怀疑。 listOfData包含什么内容,它与uc:Product有什么关系? - Jono
请问您能否就建议的解决方案提供一些反馈或更多关于您具体问题的信息? - Middletone
2个回答

3

页面加载在您的回发事件之前发生,请将事件更改为PreRender:

protected void Page_PreRender(object sender, EventArgs e)
{
    Repeater1.DataSource = listOfData;
    Repeater1.DataBind();            
}

这将在回发后绑定您的重复项并保持回发值。 编辑:

这是一张很好的图片,展示了整个WebForms页面生命周期:

正如您所看到的

ProcessPostData事件在Load事件之后被调用。

因此,您希望在处理PostData之后绑定您的Repeater

这可以在PreRender上完成。


0
问题不在于您在错误的位置调用数据绑定,而很可能是用户控件没有正确地将数据保存在视图状态中。看起来您正在使用自定义控件。如果是这种情况,您可以在用户控件上创建一个从视图状态中读取的属性。以下是一个示例:
Public Property ImportantData() As Int32
    Get
        Return ViewState("_ImportantData")
    End Get
    Set(ByVal value As Int32)
        ViewState("_ImportantData") = value
    End Set
End Property

这将使您的数据持久化,并在 postback 时保持必要的数据。

这样做是正确的,因为它只会在初始加载时加载。

protected void Page_Load(object sender, EventArgs e)
{
    if(!Page.IsPostBack)
    {
        Repeater1.DataSource = listOfData;
        Repeater1.DataBind();            
    }
    // Repeater1.DataBind(); // and tried to put DataBind() here
}

1
问题不在于您在错误的位置调用数据绑定,如果您没有使用视图状态,那么是在错误的位置进行绑定。 - Phill
他根本没有提到视图状态。从我的经验中推断,如果他正在使用自定义控件,则可以确保它会保留他的属性,这就是他的问题所在。如果没有视图状态,那么实际上需要在初始化阶段完成这项工作(作为一个编写了完全动态应用程序的人)。如果在此之后进行绑定,则在事件需要被触发时该值将丢失。事实上,如果在此之后重新绑定,则最终会使用户想要首先触发的事件无效。 - Middletone
如果他的问题是一个视图状态问题(我认为是这个原因),在渲染之前触发不会有用,值仍然会丢失。我认为你误读了他的问题,问题是缺少了一个值,而不是事件没有触发。 - Middletone
尽管我给出了一个有效的答案,而且你似乎不理解页面生命周期。你还是决定给我点踩。恭喜! - Phill
如果他实现你的解决方案,它仍然无法工作。我已经解释过原因了。 - Middletone
你错了,就这样。他的问题很容易重现,使用相同的绑定可以解决它。 - Phill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接