【问题标题】:Force Full Postback programmatically from UpdatePanel从 UpdatePanel 以编程方式强制完全回发
【发布时间】:2011-12-18 22:04:02
【问题描述】:

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

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

在这种精确场景中不起作用的解决方案(其中许多在 SO 的其他地方都有介绍):

  1. 在版本 4 之前的 ASP.NET 中,如果您将 ID 留在控件之外,它甚至会在更新面板中执行完整的回发。我的问题只针对最新最好的 .NET 4。

  2. ScriptManager.RegisterPostBackControl 看起来很有希望。它确实使控件回发使用正确的面板 ID 作为事件目标,但没有其他帮助。

  3. 将 PostBackTrigger 添加到更新面板。我的更新面板是以编程方式生成的,MS 声明这不受支持。我的测试表明它们是正确的:我尝试了各种方法,但都不起作用。

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

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

有没有人知道如何让它发挥作用?我知道很多这种应该工作,但那不完全一样。

【问题讨论】:

    标签: c# asp.net asp.net-ajax updatepanel


    【解决方案1】:

    对我来说,解决方案 3 有效。

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

    在下面查看我的测试设置。

    标记

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

    代码背后

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

    希望这会有所帮助。

    【讨论】:

    • 这对我来说行不通。如果我在创建面板时添加“postBackTrigger”,如果 button.ID 不存在(合理),它会失败,但如果我将它添加到我的自定义控件中它没有任何效果 - 暗示了一些生命周期的事情.我会坚持下去的。
    • 如果我将按钮控件放入包含更新面板的控件的 OnInit() 页面中,则按建议工作。如果我把它放在我需要的地方,在面板内自定义控件的 OnInit() 中(搜索控件层次结构以找到更新面板),那么它不起作用。更多实验..
    • 不确定这是否有帮助,但请查看这个问题(特别是答案):FileUpload in FormView inside an UpdatePanel
    • 我看过大部分问题,但没有看到答案的微妙之处。我明天试试。现在,我在所有不可见的更新面板中放置了一个链接按钮。然后在面板内的自定义 GridView 中,我找到它并将导出事件处理程序挂钩到它。最后我让 jQuery 将控件移动到网格中。这很有效,但这是对自然的犯罪!
    【解决方案2】:

    我知道这是在一年前提出的,但如果它对其他人有帮助,解决方案 2 对我有用。

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

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

    编辑 - 经过更多测试,现在看来,此方法仅在注册控件以执行完整回发和实际单击该事物之间没有回发时才有效。解决方案或 hack 是注册控件以在每个页面加载时执行完整的回发。

    【讨论】:

    • 有趣 - 我以另一种方式解决了它(不记得如何)。 “回发”警告可能是这对我不起作用的原因。
    • 拯救了我的夜晚。就我而言,我有自己的事件,它只绑定到包含 UpdatePanel 的主控件。我在页面的 OnInit 中的代码:anlagenSelector.SelectionChanged += anlagenSelector_SelectionChanged; ((ScriptManager)this.Page.Master.FindControl("scriptManager")).RegisterPostBackControl(anlagenSelector);
    【解决方案3】:

    我构建了一个类似的继承 GridView 控件,能够进行 CSV 导出。我处理它的方式是使用特制的查询字符串参数"?SortablePagableGridViewExportToCSV=XXX" 使导出按钮成为一个简单的&lt;a href&gt; 到当前页面,其中XXX 是我的控件的UniqueID。我覆盖了我的控件的 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()
    

    关键是调用Page.Response.End(),它会停止所有进一步的处理。这是一个 GET 请求,所以我不必担心 UpdatePanel 异步回发或类似的事情。浏览器在这种情况下表现得很好,弹出下载链接,但将用户留在当前页面上。浏览器 URL 不变,用户甚至可以右键单击下载链接并使用 Save Target As... 如果他们愿意。

    【讨论】:

    • 你肯定需要“响应”的东西,但我的问题更具体一点。问题是处理他们的更新面板的MS代码“snaffles”下载的文件。在更新面板之外它可以按照您的描述工作,但不能在里面。
    • @philw,您自己尝试过这种技术吗?它在使用 .NET 4.0 的 UpdatePanel 中为我工作。在这种情况下,UpdatePanel 根本不重要,因为它根本不发回,而是执行正常的 GET 请求,不会被任何 UpdatePanel AJAX 代码捕获。
    • 响应的东西,当然——你也需要添加内容长度,否则你不会得到任何进度指示器。我想(从记忆中)我真的不记得我们是如何解决这个问题的!
    【解决方案4】:

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

    这样,点击它,它将强制一个完整的回发...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-02
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-23
      • 2011-01-15
      • 2012-08-23
      相关资源
      最近更新 更多