Pregunta

He desarrollado un control personalizado que extiende ListBox.La idea es que el control "recuerde" las modificaciones de sus elementos que ocurrieron en el lado del cliente, p.como resultado de una solicitud AJAX.

La forma en que funciona es que el control también genera una entrada oculta y el resultado de la solicitud AJAX se almacena en la entrada oculta.Esto se devuelve y el método LoadPostData() del control busca la entrada oculta y, si la entrada oculta tiene datos, crea la colección ListItem a partir de ella.

Esto funciona perfectamente siempre que el usuario haya realizado una selección en el cuadro de lista.Si no es así, no se llama al método LoadPostData() y, en consecuencia, no se crea la nueva colección ListItem.(Lo establecí usando el depurador).

Supongo que el método LoadPostData solo se llama si la recopilación de datos POST incluye datos correspondientes al UniqueID del control (es decir,atributo 'nombre' en HTML).Si el usuario no ha realizado una selección en el cuadro de lista, no se incluye nada en los datos de publicación para UniqueID del cuadro de lista y no se llama a LoadPostData().¿Es eso correcto?

¿Alguien puede sugerir cómo puedo garantizar que el método LoadPostData() de mi ListBox personalizado se llame en cada devolución de datos, independientemente de si el usuario ha realizado una selección?

Gracias de antemano. Estoy realmente atrapado con este.

David

¿Fue útil?

Solución 3

He establecido que el método de LoadPostData () no se llama a menos que los datos posteriores contengan un elemento con el mismo nombre que el único de control. [Editar: Página de llamadas. RegistreRequirespostback durante init () supera esto.] Puedo ver por qué, pero es bastante limitante.

He superado el problema al no manejarlo durante el método LoadPostData () en absoluto. En su lugar, lo he manejado en un método que llamo en Onload () en su lugar.

Dos cosas deben tenerse en cuenta al usar este enfoque:

1) Ya no tiene acceso al objeto PostCollection NameValueCollection que se pasa al método LoadPostData () como argumento. Esto significa que tiene que extraer los datos posteriores de la colección Solicite.Form, que es un trabajo ligeramente más difícil. 2) Dado que Onload () se produce después del código de procesamiento de ViewState, deberá configurar manualmente el valor seleccionado después de crear los listitems. Si no lo hace, si el cuadro de lista se rellena a través de AJAX y el usuario hace una selección, la selección se perderá.

Espero que esto ayude a alguien en el futuro.

Otros consejos

Estoy un poco tarde saltando en esto, pero, solo para una referencia futura, aquí es cómo logré algo similar ...

Mi control es un árbol que usa plantillas para los nodos. El problema en el que estaba lidiando con esto fue cómo capturar los cambios laterales del cliente en el estado expandido / colapsado de los nodos. Lo que terminó trabajando fue:

En CreatechildControls Agregue el campo oculto a la colección de controles de mi control de raíz.

protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
{
    ...
    _cdExpanded = new HiddenField();
    _cdExpanded.ID = "cdExpanded";
    this.Controls.Add(_cdExpanded);
    ...
}

en la llamada ONINIT

protected override void OnInit(EventArgs e)
{
    ...
    Page.RegisterRequiresPostBack(this);
    ...
}

en loadpostdata Busque un valor en la colección POST que coincida con el UniqueID (no clientid) del campo oculto:

public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
    ...
    string cdExpanded = postCollection[_cdExpanded.UniqueID];
    ...
}

Dentro de las clases para los nodos individuales, tengo código que llena los eventos ONCLICK de mis botones de palanca con una llamada a una función JavaScript que toma la identificación del control base y los nodos individuales como argumentos.

    string ToggleScript
    {
        get
        {
            return "ToggleNode('" + this.ClientID + "', '" + _TreeRoot.ClientID + "');";
        }
    }
    protected override void Render(HtmlTextWriter writer)
    {
        ...
        if (this.HasChildren)
        {
            writer.AddAttribute("onclick", ToggleScript);
        }
        ...
    }

Esto lo hace de modo que encontrar el campo oculto es bastante fácil a través de GetElementByID:

function ToggleNode(nodeID, treeID) {
var cdExpanded = document.getElementById(treeID + "_cdExpanded");
...
}

El JavaScript luego modifica el valor del campo oculto según sea necesario para el evento que ocurrió. Cuando regresemos al servidor, puedo analizar los contenidos de este campo y modificar el estado de control según sea necesario antes de que se vuelva a renderizar. (Nota: En realidad, uso 3 campos ocultos para rastrear diferentes eventos, pero el concepto es el mismo)

Espero que esto ayude a otros en el futuro ...

Suena realmente extraño para estar funcionando solo cuando se selecciona un artículo.Una forma rápida de verificar si se invoca a loadpostdata se está invocando podría habilitar el rastreo y poner lo siguiente en iPostbackdatahandler.loadpostdata (...).

Page.Trace.Write("My control", "LoadPostData");

Si ese es el caso, debe asegurarse de que tiene lo siguiente:

Page.RegisterRequiresPostBack(this) in OnInit

Aquí hay un control de muestra completo.

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.Web.UI.Design;

namespace Controls
{
    public sealed class ExtendedListBoxDesigner : ControlDesigner
    {

        public override string GetDesignTimeHtml()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<div>My designer</div>");
            return sb.ToString();
        }

    }

    [DesignerAttribute(typeof(ExtendedListBoxDesigner), typeof(IDesigner))]
    public class ExtendedListBox : ListBox, INamingContainer, IPostBackDataHandler 
    {
        bool IPostBackDataHandler.LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
        {
            Page.Trace.Write("ExtendedListBox", "LoadPostData");
            return true;
        }


        protected override void OnInit(EventArgs e)
        {
            Page.RegisterRequiresPostBack(this);
            base.OnInit(e);
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
            base.RenderContents(writer);
            writer.Write(string.Format("<input type=\"hidden\" name=\"{0}_dummy\" value=\"alwaysPostBack\">", this.ID));
        }

    }
}

y la página se ve así.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ControlSamlpe._Default" Trace="true" %>
<%@ Register Assembly="Controls" Namespace="Controls" TagPrefix="sample" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <sample:ExtendedListBox runat="server" ID="extListBox"></sample:ExtendedListBox>
    <asp:Button runat="server" ID="go" />
    </div>
    </form>
</body>
</html>

Cuando hace clic en Ir, debe ver "Loadpostdata" en la traza.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top