我想从Codebehind显示一个jQuery UI对话框,需要在回发后刷新它。
该对话框是一个用于过滤和查找数据的控件。因此,用户从DropDownLists中选择并在TextBoxes中输入文本,单击“Apply-Button”,发生异步回发,根据用户的选择过滤数据,结果将显示在GridView中。因此,我需要更新GridView周围的UpdatePanel。
异步回发在这些链接的帮助下工作:
(基本上是dlg.parent().appendTo(jQuery("form:first"));
- 解决方案)
问题:我无法使用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)?
在异步回发之前销毁对话框无法解决问题,因为对话框将消失:
<asp:Button ID="BtnApplyFilter" OnClientClick="$('#Dialog_ChargeFilter').dialog('destroy');" ... />
非常感谢您的帮助。
解决方案:我最终使用了AjaxControlToolkit中的ModalPopupExtender。在一些小问题之后它的工作就像一个带异步回发的魅力(如果你想让弹出窗口保持可见,不要忘记在每个代码隐藏函数中调用MPE.Show()
)。如果有人感兴趣,我可以添加更多代码。
答案 0 :(得分:5)
我认为它有事可做 对话框不在里面 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 );
}
这也会混淆事件验证,因为页面的客户端和服务器版本不匹配(或者至少ASP.Net不能告诉他们这样做)。我能找到完成这项工作的唯一方法是关闭事件验证。
使用适当的安全模型,事件验证不是100%必要的,但我不喜欢被迫关闭它。
总而言之,这是我在SO上发布的最邪恶的代码,如果你使用它,蓬松的白色小猫会死掉,但这种方法确实有效。
希望这有帮助。
答案 1 :(得分:4)
以下是我解决同一问题的方法。它删除任何旧的对话框,并将新更新的对话框添加回表单,以便回发工作。我将以下代码放在一个脚本块中,该脚本块通过后面的代码中的ScriptManager.RegisterStartupScript
添加到页面中。
$('#divMyDialogAdded').remove();
$('#divMyDialog').dialog({
autoOpen: false,
modal: true
}).parent().appendTo('form:first');
$('#divMyDialog').attr('id', 'divMyDialogAdded');
答案 2 :(得分:1)
我不确定但这可能是正确的,因为当我使用
时,它的工作就形成了我AjaxControlToolkit.ToolkitScriptManager.RegisterStartupScript
试试这个吗?
ScriptManager.RegisterClientScriptBlock(Me.Page, GetType(Page), "showChargeFilterDialog", "createChargeFilterDialog();$('#Dialog_ChargeFilter').dialog('open');", True)
答案 3 :(得分:1)
我认为Jquery和脚本管理器/更新面板在生成和解析脚本时创建了它,并且你应该正确处理更新面板的Trigger中的事件,以便在代码隐藏方法中使用它:
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#代码: 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 { }
}