Pergunta

Eu tenho desenvolvido um controle personalizado que se estende de caixa de Listagem.A ideia é que o controle "lembra-se" modificações de seus elementos, que ocorreu do lado do cliente, por exemplo,como resultado de uma solicitação AJAX.

O modo como funciona é que o controle também apresenta uma entrada oculto, e o resultado da solicitação AJAX é armazenado na entrada oculto.Esta é remetida de volta, e o controle do LoadPostData() o método de procura para a entrada oculto, e se escondido entrada de dados, cria coleção ListItem a partir dele.

Isso funciona perfeitamente assim, desde que o usuário tenha feito uma seleção na caixa de listagem.Se eles não têm, os LoadPostData() o método não obter chamado, e, consequentemente, a nova coleção ListItem não é criado.(Eu já estabeleceu esta usando o depurador.)

Eu suponho que o LoadPostData método é chamado somente se o POSTO de recolha de dados que inclui dados correspondentes para o controle de Id (por exemplo,'nome' atributo em HTML).Se o usuário não tenha feito uma seleção na caixa de listagem, nada está incluído no post de dados para a lista da caixa de Id exclusivo e LoadPostData() não é chamado.Isso é correto?

Alguém pode sugerir como eu posso garantir que a minha Listagem personalizada do LoadPostData() o método é chamado de cada postback independentemente se o usuário tiver feito uma seleção?

Obrigado antecipadamente - eu realmente estou preso com esta.

David

Foi útil?

Solução 3

Eu estabeleci que o método LoadPostData () não é chamado a menos que os dados do post contenham um item com o mesmo nome que o exclusivo do controle. [Edit: chamadas page.registerrequirespotback durante o init () supera isso.] Eu posso ver por que, mas é bastante limitante.

Eu superei o problema não lidando com isso durante o método LoadPostData () em tudo. Em vez disso, eu lidei com um método que eu chamo onload () em vez disso.

Duas coisas precisam ser levadas em mente ao usar essa abordagem:

1) Você não tem mais acesso ao objeto Postcollection Namevaluecollection que é passado para o método LoadPostData () como um argumento. Isso significa que você tem que extrair os dados da postagem da coleção Request.Form, que é um trabalho ligeiramente mais difícil. 2) Como o OnLoad () ocorre após o código de processamento do ViewState, você precisará definir manualmente o SelectedValue depois de criar os listários. Se você não fizer, se a caixa de listagem é preenchida via Ajax e o usuário fizer uma seleção, a seleção será perdida.

Espero que isso ajude alguém no futuro.

Outras dicas

Estou um pouco atrasado saltar sobre isso, mas, apenas, para referência futura, aqui está como eu feito algo semelhante...

Meu controle é uma árvore que utiliza modelos para nós.O problema que eu estava lidando com isso foi como capturar o lado do cliente alterações expandido/estado recolhido de nós.O que acabou de trabalho foi:

Em CreateChildControls adicionar o campo oculto para a coleção de controles de minha raiz de controle.

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

Em OnInit chamada

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

Em LoadPostData olhar para um valor no posto de coleta, que coincide com o Id exclusivo (não ClientID) do campo oculto:

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

Dentro de classes para os nós individuais tenho o código que preenche os eventos onclick dos meus botões de alternância, com uma chamada para uma função JavaScript que leva o ID da base de controle e os nós individuais como argumentos.

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

Isso faz com que encontrar o campo oculto é bastante fácil através da transmissão:

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

O JavaScript, em seguida, modifica o valor do campo oculto na medida necessária para o evento que ocorreu.Quando chegamos de volta para o servidor que eu sou capaz de analisar o conteúdo deste campo e modificar o estado de controle conforme necessário antes que ela seja processada novamente.(Nota:Na verdade, eu uso 3 campos ocultos para o rastreamento de eventos diferentes, mas o conceito é o mesmo)

Espero que isso ajude outras pessoas no futuro...

Soa muito estranho para trabalhar somente quando um item é selecionado.Uma maneira rápida de verificar se LoadPostData está sendo invocada para ativar o rastreamento e colocar o seguinte no IPostBackDataHandler.LoadPostData(...).

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

Se for esse o caso, você deve se certificar de que você tem o seguinte:

Page.RegisterRequiresPostBack(this) in OnInit

Aqui é um exemplo de controle.

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

    }
}

e a página se parece com isso.

<%@ 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>

Quando você clique em vá, você deve ver "LoadPostData" no rastreamento.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top