2011-04-14 18 views
8

quiero mostrar un cuadro de diálogo de la interfaz de usuario jQuery de Codebehind y necesito actualizarlo después de las devoluciones.jQuery Dialog-Postback pero UpdatePanel no se actualiza

El cuadro de diálogo es un control para filtrar y buscar datos. Entonces, el usuario selecciona desde DropDownLists e ingresa texto en TextBoxes, hace clic en "Apply-Button", se produce una devolución de datos asincrónica, los datos se filtran de acuerdo con la selección del usuario y el resultado se muestra en un GridView. Por lo tanto, necesito actualizar UpdatePanel alrededor de GridView.

La devolución de datos asincrónica funciona con la ayuda de estos enlaces:

(Básicamente, el dlg.parent().appendTo(jQuery("form:first")); -Solución)

Problema: No puedo actualizar el UpdatePanel ni con UpdateMode = "Always" ni manual desde codebehind a través de UpdatePanel.Update(). Supongo que tiene algo que ver con el diálogo que no está dentro del UpdatePanel o algo similar. Espero que alguien pueda ayudarme.

Algunos fuente:

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

Se pone llamó desde código subyacente cuando BtnShowDialog (fuera del jQuery-Dialog) se hace clic a través de

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

actualización: También he notado un problema en los valores de devolución de datos. Todos los cuadros de texto si están vacíos o no tienen una coma adjunta. Esto indica que los controles se procesan varias veces de acuerdo con: http://www.componentart.com/community/forums/t/60999.aspx

Estoy seguro de que ambos problemas están relacionados. El diálogo completo con todos sus controles se recreará en cada devolución de datos asincrónica, por lo tanto, todos los nombres de control existen varias veces en el DOM (lo que causa el problema de adición de coma de ViewState). Los controles solo son visibles en FireBug/IE Deveoper Toolbar y no en HTML-Source, por lo tanto, supongo que jQuery causa estos problemas. ¿Cómo puedo disponer de el cuadro de diálogo o cómo puedo evitar la recreación (compruebe si ya existe) del cuadro de diálogo? ¿Esto es porque el diálogo está dentro de un Panel de actualización o porque se mueve (a través de Javascript) fuera de UpdatePanel?

Destruyendo el diálogo antes de la devolución de datos asincrónica no resuelve el problema porque el diálogo desaparecerá simplemente:

<asp:Button ID="BtnApplyFilter" OnClientClick="$('#Dialog_ChargeFilter').dialog('destroy');" ... /> 

Su ayuda es muy apreciada.


Solución: i terminó con el uso de la ModalPopupExtender del AjaxControlToolkit. Después de algunos pequeños problemas funciona como un encanto con devoluciones de datos asincrónicas (no olvides llamar al MPE.Show() en cada función de código subyacente si quieres que la ventana emergente permanezca visible). Podría agregar más código si alguien está interesado.

+0

Hola Tim. Tengo el mismo problema. Me pregunto si eventualmente encontraste una solución potencial para esto. Implementé el diálogo jquery en toda la aplicación, pero necesito hacer un enlace entre 2 listas desplegables en 1 de estos diálogos. Por lo tanto, cambiaría a ModalPopUpExtender como una opción final. Por favor, eche un vistazo a mi pregunta: http://stackoverflow.com/questions/8082921/dropdownlist-selected-index-changed-event-inside-jquery-dialog. Saludos, – aleafonso

Respuesta

1

No estoy seguro, pero esto es probablemente ans derecha bz su trabajo me forman cuando yo estaba usando

AjaxControlToolkit.ToolkitScriptManager.RegisterStartupScript 

probar esto?

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

Gracias, pero eso no funciona también. El contenido será el mismo aunque lo he cambiado en código subyacente y he llamado 'UpdatePanel.Update()'. –

5

supongo que tiene algo que ver con el diálogo no estar dentro de la UpdatePanel o algo similar.

También he notado un problema en postback-values. Todos los cuadros de texto si están vacíos o no tienen una coma adjunta.

Usted es realmente correcto en ambos aspectos. La clave del problema es que el Administrador de scripts "piensa" que se supone que debe actualizar un elemento que jQuery realmente ha movido a una ubicación diferente en la página, lo que resulta en múltiples copias del elemento y los problemas que ha mencionado.

He visto este problema utilizando UpdatePanels anidados, pero también puede ocurrir en otros escenarios.

Este es un problema para el cual las soluciones son complicadas.

Opción 1 - Cambiar el código fuente de jQuery UI. No tuve suerte con una solución rápida; En lugar de reescribir todo el complemento, no pude encontrar un diálogo fácil para que el diálogo funcione sin reordenar el DOM. Además, con esa ruta, ahora "posee" el código fuente porque lo ha modificado.

Opción 2: ajuste el DOM siempre que la página se represente parcialmente para eliminar los elementos duplicados. Puede generar algunos guiones adicionales para limpiar el elemento duplicado falso. No me gusta este enfoque porque permite que DOM esté en un estado inválido hasta que se ejecuta el script.

Opción 3: anule manualmente la representación del UpdatePanel. Código ve algo como esto:

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

Esto también va a confundir la validación evento porque las versiones de cliente y servidor de la página no coinciden (o al menos ASP.Net no pueden decir que lo hacen). La única forma que pude encontrar para hacer este trabajo fue desactivar la validación del evento.

Con un modelo de seguridad adecuado, la validación de eventos no es necesaria al 100%, pero no me gusta que me obliguen a desactivarla.

En resumen, este es el código más malvado que he publicado en SO y los gatitos blancos mullidos morirán si lo usa, pero el enfoque parece funcionar.

Espero que esto ayude.

+0

Gracias por esta solución. Pero mientras tanto, he renunciado al enfoque jQuery-Dialog y estoy usando el ModalPopupExtender de la última versión de AjaxControlToolkit. Funciona perfectamente con las devoluciones de datos asincrónicas después de resolver algunos problemas más pequeños, independientemente de si se abre desde el cliente o en el servidor. Gracias de nuevo :) –

4

Así es como resolví el mismo problema. Elimina todos los cuadros de diálogo antiguos y agrega el que acaba de actualizar al formulario para que las devoluciones de datos funcionen. Puse el siguiente código en un bloque de script que se agrega a la página a través del ScriptManager.RegisterStartupScript en el código subyacente.

$('#divMyDialogAdded').remove(); 

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

$('#divMyDialog').attr('id', 'divMyDialogAdded'); 
+0

Esto funcionó para mí también, aunque terminé poniéndolo en mi controlador jQuery ready y en el controlador pageLoad isPartialLoad en vez de utilizar ScriptManager. –

1

creo jQuery y scripts del panel de administrador/actualización cuando se generan y analizan secuencia de comandos creada confilct él, y usted debe manejar evento en disparador del panel de actualización correctamente con el fin de utilizar esto en código detrás método:

 UpdatePanel2.Update(); 

así que tengo este problema y puede resolverse por debajo de código (es mi código de ejemplo):

<!--------- 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> 

y en C# código: voi protegida d BtnUpMove_Click (remitente del objeto, 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 { } 

    }