jQuery Dialog-Postback但UpdatePanel没有更新

我想从Codebehind显示一个jQuery UI对话框,需要在回发后刷新它。

该对话框是一个用于过滤和查找数据的控件。 因此,用户从DropDownLists中选择并在TextBoxes中输入文本,单击“Apply-Button”,发生异步回发,根据用户的选择过滤数据,结果将显示在GridView中。 因此,我需要更新GridView周围的UpdatePanel。

异步回发在这些链接的帮助下工作:

  • 带有ASP.NET按钮回发的jQuery UI对话框
  • http://blog.roonga.com.au/2009/07/using-jquery-ui-dialog-with-aspnet-and.html

(基本上是dlg.parent().appendTo(jQuery("form:first")); -Solution)

问题 :我无法使用UpdateMode =“Always”更新UpdatePanel,也无法通过UpdatePanel.Update()从代码隐藏手动更新UpdatePanel。 我假设它与Dialog不在UpdatePanel内部或类似的东西有关。 希望有人可以帮助我。

一些来源:

 function createChargeFilterDialog() { //setup dialog $('#Dialog_ChargeFilter').dialog({ modal: true, resizable: false, autoOpen: false, draggable: true, hide: "Drop", width: 850, height: 600, position: "center", title: "Charge-Filter", buttons: { "Close": function () { $(this).dialog("close"); } }, open: function (type, data) { $(this).parent().appendTo(jQuery("form:first")) }, close: function (type, data) { } }); } 

当BtnShowDialog(在jQuery-Dialog之外)被点击时,它会从代码隐藏中调用

 AjaxControlToolkit.ToolkitScriptManager.RegisterStartupScript _ (Me.Page, GetType(Page), "showChargeFilterDialog", "createChargeFilterDialog();$('#Dialog_ChargeFilter').dialog('open');", True) 

更新 :我还注意到postback-values中存在问题。 所有TextBoxes如果为空或没有附加逗号。 这表示根据以下内容多次呈现控件: http : //www.componentart.com/community/forums/t/60999.aspx

我确信这两个问题都是相关的。 将在每个异步回发中重新创建包含其所有控件的整个对话框,因此所有控件名称在DOM中存在多次(导致ViewState逗号附加问题)。 控件只能在FireBug / IE开发工具栏中看到,而不能在HTML-Source中看到,因此我假设jQuery会导致这些问题。 如何处理对话框或如何防止对话框的重新创建 (检查是否已存在)? 这是因为对话框在UpdatePanel内部,还是因为它在UpdatePanel外移动(通过Javascript)?

在异步回发之前销毁对话框无法解决问题,因为对话框将消失:

  

非常感谢您的帮助。


解决方案 :我最后使用了AjaxControlToolkit中的ModalPopupExtender 。 在一些小问题之后它的工作就像一个带异步回发的魅力(如果你想让弹出窗口保持可见,不要忘记在每个代码隐藏函数中调用MPE.Show() )。 如果有人感兴趣,我可以添加更多代码。

我假设它与Dialog不在UpdatePanel内部或类似的东西有关。

我也注意到了回发值的问题。 所有TextBoxes如果为空或没有附加逗号。

你在两方面都是正确的。 问题的关键在于脚本管理器“认为”它应该更新jQuery实际上移动到页面上不同位置的元素,从而导致元素的多个副本和您提到的问题。

我已经使用嵌套的UpdatePanels看到了这个问题,但它也可能出现在其他场景中。

这是一个解决方法混乱的问题。

选项1 – 更改jQuery UI的源代码。 快速修复我没有任何运气; 没有重写整个插件,我找不到一个容易让对话框正常工作而无需重新排序DOM。 此外,使用该路由,现在您“拥有”源代码,因为您已修改它。

选项2 – 在部分呈现页面时调整DOM以删除重复元素。 您可以输出一些额外的脚本来清除虚假的重复元素。 我不喜欢这种方法,因为它允许DOM在脚本运行之前处于无效状态。

选项3 – 手动覆盖UpdatePanel的呈现。 代码看起来像这样:

 private bool _hasDomPresence { get { return ViewState["__hasDomPresence"] == null ? false : (bool)ViewState["__hasDomPresence"]; } set { ViewState["__hasDomPresence"] = value; } } protected override void OnLoad( EventArgs e ) { if( !ScriptManager.GetCurrent( this.Page ).IsInAsyncPostBack ) { // a full postback means we no longer have a DOM presence _hasDomPresence = false; } base.OnLoad( e ); } protected virtual void ShowDetailDialog() { // code to show the offending dialog // we are showing it, so note the fact that it now has a DOM presence _hasDomPresence = true; } protected override void Render( HtmlTextWriter writer ) { foreach( Control c in this.Controls ) { // // find the offending control's parent container prior to it being rendered // In my scenario, the parent control is just a server-side DIV if( c == this.DetailDialog ) { // // here, I am checking whether or not the panel actually needs to be // rendered. If not, I set it to invisible, thus keeping a new DOM // element from being created. if( !this.DetailUpdatePanel.IsInPartialRendering && _hasDomPresence ) { this.DetailUpdatePanel.Visible = false; } } } base.Render( writer ); } 

这也会混淆事件validation,因为页面的客户端和服务器版本不匹配(或者至少ASP.Net不能告诉他们这样做)。 我能找到完成这项工作的唯一方法是关闭事件validation。

使用适当的安全模型,事件validation不是100%必要的,但我不喜欢被迫关闭它。

总而言之,这是我在SO上发布的最邪恶的代码,如果你使用蓬松的白色小猫将会死亡,但这种方法似乎确实有效。

希望这可以帮助。

以下是我解决同一问题的方法。 它删除任何旧的对话框,并将新更新的对话框添加回表单,以便回发工作。 我将以下代码放在一个脚本块中,该脚本块通过后面的代码中的ScriptManager.RegisterStartupScript添加到页面中。

 $('#divMyDialogAdded').remove(); $('#divMyDialog').dialog({ autoOpen: false, modal: true }).parent().appendTo('form:first'); $('#divMyDialog').attr('id', 'divMyDialogAdded'); 

我不确定,但这可能是正确的,因为当我使用时,它的工作就形成了我

 AjaxControlToolkit.ToolkitScriptManager.RegisterStartupScript 

试试这个 ?

 ScriptManager.RegisterClientScriptBlock(Me.Page, GetType(Page), "showChargeFilterDialog", "createChargeFilterDialog();$('#Dialog_ChargeFilter').dialog('open');", True) 

我认为Jquery和脚本管理器/更新面板在生成和解析脚本时创建了它,并且你应该正确处理更新面板的Trigger中的事件,以便在代码隐藏方法中使用它:

  UpdatePanel2.Update(); 

所以我有这个问题,可以通过下面的代码解决它(这是我的示例代码):

   

在c#代码中:protected void BtnUpMove_Click(object sender,EventArgs e){int SelectedIndex = lstSLA.SelectedIndex;

  if (SelectedIndex == -1) // nothing selected { UpdatePanel2.Update(); return; } if (SelectedIndex == 0) // already at top of list { UpdatePanel2.Update(); return; } ListItem Temp; Temp = lstSLA.SelectedItem; lstSLA.Items.Remove(lstSLA.SelectedItem); lstSLA.Items.Insert(SelectedIndex - 1, Temp); UpdatePanel2.Update(); lstSLA.SelectedIndex = -1; } protected void BtnDownMove_Click(object sender, EventArgs e) { int SelectedIndex = lstSLA.SelectedIndex; if (SelectedIndex == -1) // nothing selected { UpdatePanel2.Update(); return; } if (SelectedIndex == lstSLA.Items.Count - 1) // already at top of list { UpdatePanel2.Update(); return; } ListItem Temp; Temp = lstSLA.SelectedItem; lstSLA.Items.Remove(lstSLA.SelectedItem); lstSLA.Items.Insert(SelectedIndex + 1, Temp); UpdatePanel2.Update(); lstSLA.SelectedIndex = -1; } protected void btnSavePeriority_Click(object sender, EventArgs e) { if (lstSLA.Items.Count == 0) return; try { var db = DatabaseHelper.GetITILDataAccess(); ServiceLevel srvlvl = new ServiceLevel(); int priority = 1; foreach (ListItem ls in lstSLA.Items) { srvlvl = new ServiceLevel(); srvlvl = db.ServiceLevels.Single(p => p.ID == long.Parse(ls.Value)); srvlvl.priority = priority; priority++; ServiceLevelManagement.Update(srvlvl); } ShowMessage(ITILMessages.InsertComplete); } catch (Exception ex) { } finally { } }