从UpdatePanel以编程方式强制完全回发

时间:2021-10-31 15:05:22

I have a GridView in an update panel. It's an inherited asp:GridView, so it has a little "export me" icon which does just that. It works by responding to an "export" click with an XLS file. The problem is that if you put the smart GridView inside an update panel, ASP.NET thinks the XLS file is to be written into the panel, which is obviously not what we want. For this, I need a full post-back every time.

我在更新面板中有一个GridView。它是一个继承的asp:GridView,所以它有一个“导出我”的图标,就是这样。它通过响应带有XLS文件的“导出”单击来工作。问题是,如果您将智能GridView放在更新面板中,ASP.NET认为XLS文件将写入面板,这显然不是我们想要的。为此,我每次都需要一个完整的回复。

My update panels are all programatically generated

我的更新面板都是以编程方式生成的

Solutions which don't work in this precise scenario (many of which are covered elsewhere on SO):

解决方案在这种精确的情况下不起作用(其中许多在SO的其他地方都有涉及):

  1. In ASP.NET before version 4, if you left the ID off a control it would do a full postback even from within an update panel. My question is for the latest and greatest .NET 4 only.

    在版本4之前的ASP.NET中,如果您将ID从控件中删除,它甚至可以在更新面板中执行完整的回发。我的问题是仅针对最新和最好的.NET 4。

  2. ScriptManager.RegisterPostBackControl looks promising. It does make the control post-back use the correct panel ID as the eventtarget, but doesn't otherwise help.

    ScriptManager.RegisterPostBackControl看起来很有前途。它确实使控制后期使用正确的面板ID作为事件目标,但没有其他帮助。

  3. Adding a PostBackTrigger to the Update panel. My update panels are generated programmatically, and MS state that this is not supported. My tests indicate that they're right: I tried it every way, but this does not work.

    将PostBackTrigger添加到“更新”面板。我的更新面板是以编程方式生成的,MS声明不支持此更新。我的测试表明他们是对的:我尝试过各种方式,但这不起作用。

  4. I don't really like the idea of the smart GridView having to break out from itself, but I tried to make it put an extra control outside the updatePanel in these circumstances. The idea being to make a client-side click on my export button inside the panel be redirected by client javascript to simulate a click on that button outside the panel. However this doesn't work because I can't apparently add the "outside" control to the page - I get the "The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases." error.

    我不太喜欢智能GridView不得不脱离自己的想法,但我试图让它在这些情况下在updatePanel之外添加一个额外的控件。通过客户端javascript重定向客户端单击面板内的导出按钮的想法,以模拟面板外部的该按钮的单击。但是这不起作用,因为我无法将“外部”控件添加到页面中 - 我得到“在DataBind,Init,Load,PreRender或Unload阶段不能修改控件集合”。错误。

  5. Using jQuery to shift the "export" control outside the panel. MS must have some list of controls which they think are "in" the panel, and the physical location within the DOM doesn't matter.

    使用jQuery将“导出”控件移到面板外部。 MS必须有一些他们认为在面板中“控制”的控件列表,并且DOM中的物理位置无关紧要。

Does anyone have any ideas how to make that work? I know a lot of this should work, but that's not quite the same thing.

有没有人有任何想法如何使这项工作?我知道很多这个应该有用,但那不是一回事。

4 个解决方案

#1


4  

For me, solution 3 works.

对我来说,解决方案3可行。

I dynamically add an UpdatePanel to the page, add a Button to the content template and associate a PostBackTrigger. I added a Click event handler in which I update a label (outside of the UpdatePanel) with the current date/time.

我动态地向页面添加UpdatePanel,向内容模板添加Button并关联PostBackTrigger。我添加了一个Click事件处理程序,在其中我使用当前日期/时间更新标签(在UpdatePanel之外)。

See my test setup below.

请参阅下面的测试设置。

Markup

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:Panel ID="Panel1" runat="server"></asp:Panel>
<asp:Label ID="Label1" runat="server"></asp:Label>

Code Behind

protected void Page_Load(object sender, EventArgs e)
{
    string buttonId = "Button1";

    UpdatePanel updatePanel = new UpdatePanel();
    updatePanel.ID = "UpdatePanel1";

    Button button = new Button();
    button.ID = "Button1";
    button.Text = "Post back";
    button.Click += new EventHandler(button_Click);

    updatePanel.Triggers.Add(new PostBackTrigger() { ControlID = buttonId});

    updatePanel.ContentTemplateContainer.Controls.Add(button);

    Panel1.Controls.Add(updatePanel);
}

void button_Click(object sender, EventArgs e)
{
    Label1.Text = string.Format("Current date/time: {0}", DateTime.Now.ToString());
}

Hope this helps.

希望这可以帮助。

#2


3  

I realise this was asked a year ago but if it helps anyone else, solution 2 worked for me.

我意识到这是在一年前被问到的,但如果它对其他人有帮助,那么解决方案2对我有用。

((ScriptManager)this.Page.Master.FindControl("scrptmgr")).RegisterPostBackControl(lnkbtn);

The only way I can get it to work is if the control (in this case lnkbtn) is visible when the above line of code runs.

我可以让它工作的唯一方法是,当上面的代码行运行时,控件(在本例中为lnkbtn)是可见的。

Edit - After more testing it now seems that this method only works if there are no postbacks in between registering the control to do a full postback and actually clicking the thing. The solution or hack is to register the control to do a full postback on each page load.

编辑 - 经过更多测试后,现在看来这个方法只有在注册控件执行完全回发和实际点击之间没有回发时才有效。解决方案或hack是注册控件以在每个页面加载上执行完整回发。

#3


0  

I built a similar inherited GridView control with the ability to do CSV export. The way I handled it is to make the export button a simple <a href> to the current page with a specially-crafted querystring parameter "?SortablePagableGridViewExportToCSV=XXX" where XXX is the UniqueID of my control. I override the Render method of my control, and in there I check the request parameters manually to see if that export param was sent. If so, I write the CSV content type header and response as below.

我构建了一个类似的继承GridView控件,可以进行CSV导出。我处理它的方法是使导出按钮成为当前页面的简单,其中包含一个特制的查询字符串参数“?SortablePagableGridViewExportToCSV = XXX”,其中XXX是我的控件的唯一ID。我重写我的控件的Render方法,并在那里我手动检查请求参数,看看是否发送了导出参数。如果是这样,我写下CSV内容类型标题和响应,如下所示。

Me.Page.Response.Clear()
Me.Page.Response.ClearContent()
Me.Page.Response.ClearHeaders()
Me.Page.Response.ContentType = "text/csv"
Me.Page.Response.AddHeader("Content-Disposition", "attachment;filename=" & Me.ExportToCsvFileName)
Me.Page.Response.End()

The key is the call to Page.Response.End(), which stops all further processing. This is a GET request so I don't have to worry about UpdatePanel asynch postbacks or anything like that. The browser behaves beautifully in this situation, popping up the download link but keeping the user on the current page. The browser URL does not change, and the user can even right-click the download link and use Save Target As... if they wish.

关键是调用Page.Response.End(),它会停止所有进一步的处理。这是一个GET请求,所以我不必担心UpdatePanel异步回发或类似的事情。在这种情况下,浏览器表现得非常漂亮,弹出下载链接,但保持用户在当前页面上。浏览器URL不会更改,用户甚至可以右键单击下载链接并使用目标另存为...如果愿意。

#4


0  

In case the control that should force the page postback (suppose a button) is --inside-- a GridView templatefield, you may have some problems setting the controlId for the UpdatePanel trigger... in this case you can simply go to the teemplatefield button and set its "PostBackUrl" property to... the same page itself!

如果应该强制页面回发的控件(假设一个按钮)是--inside--一个GridView模板字段,您可能在设置UpdatePanel触发器的controlId时遇到一些问题...在这种情况下,您可以直接进入teemplatefield按钮并将其“PostBackUrl”属性设置为...同一页面本身!

This way, clicking it, it will force a full postback...

这样点击它就会强制完全回发......

#1


4  

For me, solution 3 works.

对我来说,解决方案3可行。

I dynamically add an UpdatePanel to the page, add a Button to the content template and associate a PostBackTrigger. I added a Click event handler in which I update a label (outside of the UpdatePanel) with the current date/time.

我动态地向页面添加UpdatePanel,向内容模板添加Button并关联PostBackTrigger。我添加了一个Click事件处理程序,在其中我使用当前日期/时间更新标签(在UpdatePanel之外)。

See my test setup below.

请参阅下面的测试设置。

Markup

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:Panel ID="Panel1" runat="server"></asp:Panel>
<asp:Label ID="Label1" runat="server"></asp:Label>

Code Behind

protected void Page_Load(object sender, EventArgs e)
{
    string buttonId = "Button1";

    UpdatePanel updatePanel = new UpdatePanel();
    updatePanel.ID = "UpdatePanel1";

    Button button = new Button();
    button.ID = "Button1";
    button.Text = "Post back";
    button.Click += new EventHandler(button_Click);

    updatePanel.Triggers.Add(new PostBackTrigger() { ControlID = buttonId});

    updatePanel.ContentTemplateContainer.Controls.Add(button);

    Panel1.Controls.Add(updatePanel);
}

void button_Click(object sender, EventArgs e)
{
    Label1.Text = string.Format("Current date/time: {0}", DateTime.Now.ToString());
}

Hope this helps.

希望这可以帮助。

#2


3  

I realise this was asked a year ago but if it helps anyone else, solution 2 worked for me.

我意识到这是在一年前被问到的,但如果它对其他人有帮助,那么解决方案2对我有用。

((ScriptManager)this.Page.Master.FindControl("scrptmgr")).RegisterPostBackControl(lnkbtn);

The only way I can get it to work is if the control (in this case lnkbtn) is visible when the above line of code runs.

我可以让它工作的唯一方法是,当上面的代码行运行时,控件(在本例中为lnkbtn)是可见的。

Edit - After more testing it now seems that this method only works if there are no postbacks in between registering the control to do a full postback and actually clicking the thing. The solution or hack is to register the control to do a full postback on each page load.

编辑 - 经过更多测试后,现在看来这个方法只有在注册控件执行完全回发和实际点击之间没有回发时才有效。解决方案或hack是注册控件以在每个页面加载上执行完整回发。

#3


0  

I built a similar inherited GridView control with the ability to do CSV export. The way I handled it is to make the export button a simple <a href> to the current page with a specially-crafted querystring parameter "?SortablePagableGridViewExportToCSV=XXX" where XXX is the UniqueID of my control. I override the Render method of my control, and in there I check the request parameters manually to see if that export param was sent. If so, I write the CSV content type header and response as below.

我构建了一个类似的继承GridView控件,可以进行CSV导出。我处理它的方法是使导出按钮成为当前页面的简单,其中包含一个特制的查询字符串参数“?SortablePagableGridViewExportToCSV = XXX”,其中XXX是我的控件的唯一ID。我重写我的控件的Render方法,并在那里我手动检查请求参数,看看是否发送了导出参数。如果是这样,我写下CSV内容类型标题和响应,如下所示。

Me.Page.Response.Clear()
Me.Page.Response.ClearContent()
Me.Page.Response.ClearHeaders()
Me.Page.Response.ContentType = "text/csv"
Me.Page.Response.AddHeader("Content-Disposition", "attachment;filename=" & Me.ExportToCsvFileName)
Me.Page.Response.End()

The key is the call to Page.Response.End(), which stops all further processing. This is a GET request so I don't have to worry about UpdatePanel asynch postbacks or anything like that. The browser behaves beautifully in this situation, popping up the download link but keeping the user on the current page. The browser URL does not change, and the user can even right-click the download link and use Save Target As... if they wish.

关键是调用Page.Response.End(),它会停止所有进一步的处理。这是一个GET请求,所以我不必担心UpdatePanel异步回发或类似的事情。在这种情况下,浏览器表现得非常漂亮,弹出下载链接,但保持用户在当前页面上。浏览器URL不会更改,用户甚至可以右键单击下载链接并使用目标另存为...如果愿意。

#4


0  

In case the control that should force the page postback (suppose a button) is --inside-- a GridView templatefield, you may have some problems setting the controlId for the UpdatePanel trigger... in this case you can simply go to the teemplatefield button and set its "PostBackUrl" property to... the same page itself!

如果应该强制页面回发的控件(假设一个按钮)是--inside--一个GridView模板字段,您可能在设置UpdatePanel触发器的controlId时遇到一些问题...在这种情况下,您可以直接进入teemplatefield按钮并将其“PostBackUrl”属性设置为...同一页面本身!

This way, clicking it, it will force a full postback...

这样点击它就会强制完全回发......