jQuery对话框回发,但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 (基本上是“ 0”解决方案) 问题:我无法使用UpdateMode = \“ Always \”或通过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)
更新:我也注意到回发值有问题。所有TextBoxes(如果为空或不带逗号)。这表明控件根据以下内容多次渲染:http://www.componentart.com/community/forums/t/60999.aspx 我确定这两个问题都有关。整个对话框及其所有控件将在每次异步回发中重新创建,因此所有控件名称在DOM中存在多次(导致出现ViewState逗号附加问题)。这些控件仅在FireBug / IE Deveoper工具栏中可见,而在HTML-Source中不可见,因此我认为jQuery会导致这些问题。如何处置对话框或如何防止重新创建对话框(检查是否已存在)?这是因为对话框位于UpdatePanel内,还是因为对话框(通过Javascript)已移至UpdatePanel之外? 在异步回发之前销毁对话框并不能解决问题,因为对话框将完全消失:
<asp:Button ID=\"BtnApplyFilter\" OnClientClick=\"$(\'#Dialog_ChargeFilter\').dialog(\'destroy\');\" ... />
非常感谢您的帮助。 解决方案:我最后使用了AjaxControlToolkit中的ModalPopupExtender。在一些小问题之后,它的工作原理就像异步回发一样(如果您希望弹出窗口保持可见,请不要忘记在每个代码隐藏函数中都调用
MPE.Show()
)。如果有人感兴趣,我可以添加更多代码。     

解决方法

  我认为这有事要做   对话框不在其中   UpdatePanel或类似的东西。      我也注意到了   回发值。所有文本框,如果   空的或没有附加逗号。 您确实在两个方面都正确。问题的症结在于脚本管理器“认为”应该更新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 );
}
由于页面的客户端和服务器版本不匹配(或者至少ASP.Net无法确定它们是否匹配),这也会使事件验证混乱。我可以找到的唯一方法是关闭事件验证。 使用适当的安全模型,事件验证不是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和脚本管理器/更新面板在生成和解析脚本时会使其冲突,因此您应该正确处理更新面板的触发器中的事件,以便在方法后面的代码中使用此事件:
       UpdatePanel2.Update();
所以我有这个问题,可以通过下面的代码解决(这是我的示例代码):
   <!--------- show for dialog --->
<div id=\"dialog\" style=\"direction: rtl;\">
    <asp:ScriptManager ID=\"ScriptManager1\" runat=\"server\">
    </asp:ScriptManager>
    <asp:UpdatePanel ID=\"UpdatePanel2\" runat=\"server\" RenderMode=\"Block\" UpdateMode=\"Conditional\" EnableViewState=\"True\" ChildrenAsTriggers=\"True\">
        <ContentTemplate>
            <div>
                <table>
                    <tr>
                        <td>
                            <asp:ListBox ID=\"lstSLA\" runat=\"server\" SelectionMode=\"Single\" Width=\"250px\" Height=\"350px\">
                            </asp:ListBox>
                        </td>
                        <td valign=\"middle\">
                            <asp:Button ID=\"BtnUpMove\" runat=\"server\" Text=\" top\" OnClick=\"BtnUpMove_Click\" />
                            <div>
                                <br />
                            </div>
                            <asp:Button ID=\"BtnDownMove\" runat=\"server\" Text=\"down\" OnClick=\"BtnDownMove_Click\" />
                        </td>
                    </tr>
                    <tr>
                        <td colspan=\"2\" align=\"center\">
                            <asp:Button ID=\"btnSavePeriority\" runat=\"server\" Text=\"Save\" OnClick=\"btnSavePeriority_Click\" />
                        </td>
                        <td>
                        </td>
                    </tr>
                </table>
            </div>
        </ContentTemplate>
        <Triggers>
            <asp:PostBackTrigger ControlID=\"btnSavePeriority\" />
            <asp:AsyncPostBackTrigger ControlID=\"BtnUpMove\" EventName=\"Click\" />
            <asp:AsyncPostBackTrigger ControlID=\"BtnDownMove\" EventName=\"Click\" />
        </Triggers>
    </asp:UpdatePanel>
</div>
并在C#代码中:       受保护的void BtnUpMove_Click(对象发送者,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 { }

    }