Registrar arreglo de ASP.NET en el cliente para utilizarlo con Javascript

Esto vas mas allá de un estructura de matriz/arreglo de .NET sino que la idea es como registrar en el cliente una variable que corresponda a un arreglo para poder utilizarlo desde funciones Javascript.

Es decir, tener en el cliente algo así:  

<script type="text/javascript">
//<![CDATA[
var miArreglo =  new Array('Item1', ' Item2', ' Item3');
//]]>
</script>
Las opciones:

Que si lo vemos así diremos» y para «que nos puede servir??»…
Un ejemplo podría ser cuando necesitamos todos los controles de checkbox de una grilla dentro de un arreglo para manipularlo por Javascript

image

 

 

Soluciones

Veamos las opciones que tenemos para registrar un arreglo desde el codebehind de .NET hacia la pagina para manipularlo con JavaScript

 

    • OPCION 1: Registrar el arreglo manualmente… como siempre digo «artesanalmente»

      Aquí estamos nuevamente con escritura directa en la pagina, no con ResponseWrite (como lo hacíamos hace un par de años con ASP clásico) sino con métodos especiales que nos ayuden a «controlar» esta escritura de script.
      En esta oportunidad como utilizaremos RegisterClientScriptBlock de la clase ClientScriptManager, debemos también escribir el tag <script..>, o utilizar una sobrecarga del método que escribe por nosotros el tag
      Ejemplo:
      (mas abajo esta el enlace para descargar el ejemplo completo)
      image
      Para registrar el arreglo, que en este ejemplo lo tomamos de una cadena separada por comas (mas adelante veremos el ejemplo con los checkbox)

      Protected Sub btnArregloBasicoRegistrar_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnArregloBasicoRegistrar.Click
          Dim cadena() As String = txtArregloBasico.Text.ToString.Split(",")
          Dim arregloScript As New StringBuilder
          For i As Integer = 0 To cadena.Length - 1
              arregloScript.Append("'")
              arregloScript.Append(cadena(i))
              arregloScript.Append("'")
      
              If i <> (cadena.Length - 1) Then
                  arregloScript.Append(", ")
              End If
          Next
      
          'Armar Script
          Dim script As New StringBuilder
          script.Append("<script type=""text/javascript"">")
          script.Append(vbCrLf)
          script.Append("var ArregloBasico =  new Array(")
          script.Append(arregloScript.ToString)
          script.Append(");")
          script.Append(vbCrLf)
          script.Append("</script>")
      
      
          'Registrar Script
          Page.ClientScript.RegisterClientScriptBlock(Me.GetType, "ARREGLOBASICO", script.ToString)
      
      
      End Sub

      Aquí como vemos primeramente obtengo el arreglo a partir de la cadena (con el famoso método split), luego genero el script para registra el arreglo.
      El resultado en la pagina es:

      <script type="text/javascript">
      var ArregloBasico =  new Array('C-3PO', ' R2-D2');
      </script>

      Si utilizáramos la sobrecarga con el método RegisterClientScriptBlock que contiene el booleano para que escriba directamente el TAG <script>

      Page.ClientScript.RegisterClientScriptBlock(Me.GetType, "ARREGLOBASICO", script.ToString, True)

      La salida es:

      <script type="text/javascript">
      //<![CDATA[
      var ArregloBasico =  new Array('C-3PO', ' R2-D2');
      //]]>
      </script>

      Para verificar/utilizarlo en el cliente llamo a la funcion VerificarArreglo que me imprime el contenido
      image
      Lo llamo desde un simple enlace:

      <a href="#" onclick="VerificarArreglo(ArregloBasico);">Verificar Arreglo Basico en el cliente</a>

      La función es:

      <script type="text/javascript">
      
          function VerificarArreglo(arregloId){
              var cantidadItems = arregloId.length;
              var mensaje = '';
              for(i=0; i<cantidadItems; i++) { 
                 mensaje = mensaje+"Item: "+arregloId[i]+'n';
              }
          
              alert(mensaje);
          }
      </script> 

       

    •  OPCION 2: Utilizando el método ClientScript.RegisterArrayDeclaration

      Para automatizar la creación de array del lado del cliente, tenemos el método RegisterArrayDeclaration tambien de la clase ClientScriptManager
      Ejemplo:
      image

    • Código para registrar el arreglo…

      Protected Sub btnArregloRegistrar_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnArregloRegistrar.Click
              Dim cadena() As String = txtArregloEjemplo.Text.ToString.Split(",")
              For i As Integer = 0 To cadena.Length - 1
                  Page.ClientScript.RegisterArrayDeclaration("ArregloEjemplo", String.Concat("'", cadena(i), "'"))
              Next
      End Sub

      En el cliente nos queda registrado:

      <script type="text/javascript">
      //<![CDATA[
      var ArregloEjemplo =  new Array('Yoda', ' Luke', ' Obi-Wan', ' R2-D2', ' C-3PO');
      //]]>
      </script>

      Para utilizarlo desde Javascript, en el ejemplo llamo a la función que veníamos utilizando en la opción 1, pero aquí tengo que enviar como parámetro el nuevo arreglo.

      <a href="#" onclick="VerificarArreglo(ArregloEjemplo);">Verificar Arreglo en el cliente</a>
       
      Resultado:
      image

       

       


    • OPCION 3: y cuando tenemos dentro de un UpdatePanel? Utilizamos ScriptManager.RegisterArrayDeclaration

      Cambia un poco cuando necesitamos registrar elementos de script del cliente en un ambiente asíncrono, o mejor dicho cuando el contenido no se setea en la carga la pagina sino cuando se actualiza parte de ella… el típico caso del UpdatePanel, alli nuestra ayuda viene por parte del ScriptManager con el Método análogo al anterior RegisterArrayDeclaration

      Ejemplo:

      image

      La registración, con un poco de efecto para visualizar la actualización del UP 😉

      Protected Sub btnArregloRegistrarEnUpdatePanel_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnArregloRegistrarEnUpdatePanel.Click
          System.Threading.Thread.Sleep(2000)
          Dim cadena() As String = txtArregloEnUpdatePanel.Text.ToString.Split(",")
          For i As Integer = 0 To cadena.Length - 1
              ScriptManager.RegisterArrayDeclaration(Me, "ArregloEnUpdatePanel", String.Concat("'", cadena(i), "'"))
          Next
      End Sub

      Aquí la registración es «on-tle-fly» o como lo quieras llamar, la idea es que no podremos visualizarlo en el código del renderizado de la pagina. Pero si consultamos luego (con el mismo método que veníamos utilizando) llamando a una funcion javascript desde un enlace «fuera» del update panel:

      <a href="#" onclick="VerificarArreglo(ArregloEnUpdatePanel);">Verificar Arreglo En Update Panel en el cliente</a>

      Resultado:
      image

       

Ejemplo con Gridview y Checkbox


Vamos a utilizar la registración para tener en el cliente los ID de los checkbox de un Gridview, y poder manipularlos. La version «light» de este ejemplo solo contaremos las filas seleccionadas. Pero puedes agregar mas funcionalidad…
Tenemos un Gridview :
image

El checkbox lo hacemos en una columna template

<asp:GridView ID="GridView1" runat="server">
           <Columns>
               <asp:TemplateField>
                   <ItemTemplate>
                       <asp:CheckBox ID="chk" runat="server" />
                   </ItemTemplate>
               </asp:TemplateField>
           </Columns>
       </asp:GridView>

Y lo cargamos en el load de la pagina, de una manera simple:

Private Sub CargarGrilla()
      Dim dt As New Data.DataTable

      dt.Columns.Add("Nombre")

      dt.Rows.Add("Yoda")
      dt.Rows.Add("Luke")
      dt.Rows.Add("Obi-Wan")
      dt.Rows.Add("R2-D2")
      dt.Rows.Add("C-3PO")

      GridView1.DataSource = dt
      GridView1.DataBind()
  End Sub

En el evento Databound de la grilla, registramos nuestro arreglo de checkbox, llamado «aGrillaCheck»

Protected Sub GridView1_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.DataBound

       For Each fila As GridViewRow In GridView1.Rows
           'Recuperando el checkbox
           Dim chk As CheckBox = CType(fila.FindControl("chk"), CheckBox)

           Page.ClientScript.RegisterArrayDeclaration("aGrillaCheck", String.Concat("'", chk.ClientID, "'"))
       Next
     
   End Sub

Para verificar la cantidad de checkbox seleccionamos,  lo recorremos a todos

<a href="#" onclick="VerificarGrillaCheck(aGrillaCheck);">Verificar Check de la grilla en el cliente</a>
La función Javascript que realiza esto:
<script type="text/javascript">
   
    function VerificarGrillaCheck(arregloCheck){
        var cantidadCheck = arregloCheck.length;
        var cantidadSeleccionados = 0;
        var mensaje = '';
        
        for(i=0; i<cantidadCheck; i++) { 
               var chk = document.getElementById(arregloCheck[i]);
               if (chk.checked==true){
                    cantidadSeleccionados = cantidadSeleccionados+1;
               }
        }
        
        mensaje = "Seleccionados: "+cantidadSeleccionados;    
        alert(mensaje);
    }


</script>
 
Entonces el resultado podemos:
image
 
 
 

Descargar demo

(es una pagina con codebehind)
 
 
 

Enlaces:

Generar HTMLTable on-the-fly. Asignar texto a la celda (HTML, Controles, Texto)

Como resultado de preguntas en los grupos de noticias, sobre generar Tablas HTML y porque acabo de leer el articulo de Sergio (el cual recomiendo)

Quisiera agregar un TIP mas… (que le hace una mancha mas al tigre?)

  • Como crear una Tabla on-the-fly
  • Insertar contenido dentro de la celdas (HTML, Controles, texto puro formateado)
  • Insertar en la pagina web en una ubicación determinada

 

Creando Tabla on-the-fly

Veamos una función básica… que nos devuelva una HTMLTable

Private Function GenerarTabla(ByVal filas As Integer, ByVal columnas As Integer) As HtmlTable
        Dim t As New HtmlTable

        For i As Integer = 1 To filas
            Dim fila As New HtmlTableRow
            For j As Integer = 1 To columnas

                Dim celda As New HtmlTableCell

                'Insertar contenido html dentro de la celda
                '   <td><strong>ejemplo<strong><td>
                celda.InnerHtml = "<strong>ejemplo<strong>"

                fila.Cells.Add(celda)
            Next
            t.Rows.Add(fila)
        Next

        Return t
    End Function

Demasiado básico, aquí podrías agregar propiedades de estilos CSS a la fila y/o celdas… pero no vienen al tema central 😉
PERO SI ES LA RECOMENDACION… todo lo referente a estética (nada de estructura) que sea manejado con estilos CSS (colores, dimensiones, posiciones, etc)

Insertar contenido dentro de la celdas (HTML, Controles, texto puro formateado)

  • Contenido HTML

    Mediante la propiedad InnerHtml de las celda podremos insertar contenido html.
    Hay que mirarlo con mucha atención ya que lo que escribes va directamente «así como esta», y puede ser causante de algunos «fallas» ya que es posible insertar html (es decir cualquier cosa)

  • 'Insertar contenido html dentro de la celda
    '   <td><strong>ejemplo<strong><td>
    celda.InnerHtml = "<strong>ejemplo<strong>"

El resultado:

image

  • Insertar Controles

    Mediante la colecciones de controles de la celda podemos:

  • 'Insert un control
    Dim txt As New TextBox
    txt.Text = "Yoda"
    celda.Controls.Add(txt)
     

El resultado:
image

 

  • Contenido Texto

    Siempre necesitamos insertar texto puro, pero que en ocasiones puede traer amigos «no compatibles» con HTML, es decir caracteres < o > que si colocamos en la pagina tal cual el navegador interpretara como si fuera HTML y nuestra pagina quedaría mal formada… Aquí siempre nos ayudamos con HttpUtility.HtmlEncode, pero en este caso no necesitamos ya que la celda tiene una propiedad llamada InnerText

  • ''Insertar contenido texto (formateado) dentro de la celda
    ''Contenido: <strong>ejemplo<strong> 
    celda.InnerText = "<strong>ejemplo<strong>"

También aquí puedes leer otro articulo: Simple pero poderozo: Literal webcontrol

Resultado:
image
Esto quiere decir que nos ayuda a escribir contenido formateado para HTML
image

 

NOTA:

Estas propiedades no son solo para las Celdas de una tabla, sino que para todos los objetos que heredan de HtmlContainerControl, que no son mas que los que se necesita abrir y cerrar un TAG.
Por ejemplo: <form>, <table>, <tr>, <td>, <a> y <span>

 

 

Insertar en la pagina web en una ubicación determinada

La pregunta siguiente es: y Que hacemos con la tabla en el código? YO QUIERO EN LA PAGINA
Pero siempre necesitamos en ese lugar que no sabemos como «insertarla directamente», aquí la estrategia es ayudarnos por un control contenedor… como el Panel

Es decir tenemos en una pagina, en la posición que deseamos un simple Panel:

<asp:Panel ID="Panel1" runat="server">
        </asp:Panel>

Que si asignamos un estilo CSS podremos ubicarlo donde queramos, así no estamos sujeto  a ninguna restricción.

Dim tabla As HtmlTable = GenerarTabla(txtFilas.Text, txtColumnas.Text)
Panel1.Controls.Add(tabla)

 

 

 

 

Enlaces:

Jugando al detective con HttpBrowserCapabilities, preguntando propiedades del browser en ASP.NET

Cual es el browser tiene mi cliente? que versión? soporta JavaScript? Poder utilizar la detección del browser para escribir propiedades especificas en webcontrol, así:

<asp:Label ID="lbl1" runat="server" 
           Text="Mensaje (general)"  
           ie:Text="Mensaje solo para IE"
           mozillafirefox:Text="Mensaje para Firefox"
           safari:Text="Mensaje para Safari" />

Jugando al detective con HttpBrowserCapabilities

Podemos utilizar esta clase para preguntar sobre «capacidades» del browser del cliente.

Ejemplo de estas propiedades:

Propiedades… Resultado en IE7 Firefox
Type
Obtiene el nombre y el número de versión
principal (a la izquierda del separador) del
explorador
Browser
Obtiene la cadena del explorador (si existe) que
éste ha enviado en el encabezado de la solicitud
User-Agent.

(más propiedades…)

Type: IE7
Browser: IE
Version: 7.0
MajorVersion: 7
MinorVersionString: .0
MinorVersion: 0
Tables: True
Cookies: True
V B S c r i p t : True (*)
J a v a S c r i p t: True (*)
JavaApplets: True
JScriptVersion: 5.6
ActiveXControls: True

Type: Firefox2.0.0.14
Browser: Firefox
Version: 2.0.0.14
MajorVersion: 2
MinorVersionString: .0.0.14
MinorVersion: 0
Tables: True
Cookies: True
V B S c r i p t : False (*)
J a v a S c r i  p t: True (*)
JavaApplets: True
JScriptVersion: 0.0
ActiveXControls: False

(*) Separación de letras únicamente para que pueda publicar en el blog.
Existe una lista de propiedades que posee la clase HttpBrowserCapabilities.

Para el ejemplo de escribir propiedades especificas necesitamos el Browser.Id
   Request.Browser.Id

 

Como recorrer todas las propiedades…?

Aquí Reflection a nuestra ayuda….

Private Function ArmarTodasLasPropiedades() As String
       Dim bc As HttpBrowserCapabilities = Request.Browser
       Dim tipoControl As Type = bc.GetType
       Dim msj As New Text.StringBuilder

       'Listado de propiedades
       Dim propiedades() As System.Reflection.PropertyInfo = tipoControl.GetProperties

       'Recorriendo las propiedades y sus valores
       For Each p As System.Reflection.PropertyInfo In propiedades
           Dim nombre As String = p.Name
           Dim valor As String
           Try
               valor = Convert.ToString(p.GetValue(bc, Nothing))
           Catch ex As Exception
               valor = "ERROR"
           End Try

           'Armando visualizacion
           msj.Append(nombre)
           msj.Append(": ")
           msj.Append(valor)
           msj.Append(vbCrLf)
       Next

       Return msj.ToString


   End Function

 

Pero… (siempre hay «peros») no detecta la configuración del usuario actual

Es decir con esta investigación (a medias) solo logramos detectar las capacidades «inherentes» del explorador, pero no refleja como el usuario tiene actualmente configurado
Si el usuario deshabilitó JavaScript, y el navegador lo soporta, tendremos la propiedad: JavaScript=True.

Si quieres detectar la configuración del usuario hay un componente pago para detectar incluso plugins como Flash, se llama BrowserHawk, para detección avanzada 😉
Demo: http://www.cyscape.com/showbrow.aspx?bhcp=1

Sigamos con lo nuestro…HttpBrowserCapabilities

La magia?

(un poco de historia para nostálgicos…)
Antes en ASP Clásico hacíamos uso de un componente del lado del servidor de Microsoft Browser Capabilities Component (Browscap.dll) y un archivo de texto (Browscap.ini) que era el mapeador entre el browser y las capacidades…
Algo asi:

Set BrowserType = Server.CreateObject("MSWC.BrowserType")

(que buenos y no tan buenos recuerdos del SET)

y el archivo Browscap.ini:

[AOL 9.0/IE 7.0]
Parent=DefaultProperties
Browser=AOL
Version=7.0
MajorVer=7
Win32=true
Frames=true
IFrames=true
Tables=true …

Este archivo, si lo pensamos detenidamente, por cada generación nueva de navegadores y con la salida de otros había que actualizar… (siempre hay que actualizar) para eso este sitio Browser Capabilities Project

En mi querido WinXP estan aquí:
image

 

y con .NET 1.1

Ya no teníamos archivos de configuración .ini ahora tenemos .config, entonces? a escribir en el config.
para que este disponible en todas las aplicaciones se encuentra en el machine.config, seccion browseCaps
Si quieres verlo:

Archivo: C:WINDOWSMicrosoft.NETFrameworkv1.1.4322CONFIGmachine.config
Sección: <browserCaps>

(actualizar el browserCaps para ASP.NET 1.1 aquí)

y ahora? donde está en ASP.NET 2.0?

Si ves el archivo anterior tenemos un «kilometraje» bastante importante de configuración…
En ASP.NET 2.0 se no se utiliza la sección browserCaps (aunque se mantiene…se la puede utilizar combinando las dos fuentes de información)
Ahora los datos de capacidades de navegadores están ubicados en archivos de definición de explorador (extension .browser) en la carpeta:
   C:WINDOWSMicrosoft.NETFrameworkv2.0.50727CONFIGBrowsers
y si en nuestro aplicación podemos introducir en la carpeta App_Browser

 

NOTA 1: Si cambiamos algún archivo .browser en nuestra aplicación (directorio App_Browser), la aplicacion se compilara nuevamente en la proxima te peticion

NOTA 2: Si cambiamos algún archivo .browser en el directorio del framework ({windir}Microsoft.NETFramework{version}CONFIGBrowsers) vamos a tener que regenerar el assembly correspondiente con la herramienta Aspnet_regbrowsers.exe, que compila y la coloca en el GAC. Esto también lo puedes hacer por codigo con BrowserCapabilitiesCodeGenerator.

Pero no es recomendable modificar las que trae por defecto .NET sino mas bien agregar nuevos archivos, porque en algunos service pack se pueden actualizar.

Ejemplo de un archivo:

{windir}Microsoft.NETFrameworkv2.0.50727CONFIGBrowsersmozilla.browser

<!-- sample UA "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7) Gecko/20040707 Firefox/0.9.2" -->
    <browser id="MozillaFirefox" parentID="MozillaRV">
        <identification>
            <userAgent match="Gecko/d+ Firefox/(?'version'(?'major'd+)(?'minor'.[.d]*))" />
        </identification>

        <capabilities>
            <capability name="browser"                         value="Firefox" />
            <capability name="majorversion"                    value="${major}" />
            <capability name="minorversion"                    value="${minor}" />
            <capability name="version"                         value="${version}" />
            <capability name="type"                            value="Firefox${version}" />
        </capabilities>
    </browser>
....

Entonces con el ID que podemos personalizar las propiedades de nuestro webcontrol

<asp:Label ID="lbl1" runat="server" 
           Text="Mensaje (general)"  
           ie:Text="Mensaje solo para IE"
           mozillafirefox:Text="Mensaje para Firefox"
           safari:Text="Mensaje para Safari" />

 

 

 

 

Enlaces

MSDN Ramp Up. Developer Training Program. Empujón y premios para aprender .NET

image

image

http://msdn.microsoft.com/en-us/rampup/default.aspx

Siguiendo con la línea de otra entrada en mi blog:
   – Manuales, libros, enlaces sobre ASP.NET 2.0 (recopilación…)

Parece que existe este programa desde hace varios meses, pero recién hoy me entere y así que lo comparto.

Para los que necesitan empezar o darle un empujón al camino del desarrollo en .NET, existe un programa de estudio llamado MSDN Ramp Up. Interesante porque no es un solo temario para todos sino que dependiendo de nuestros conocimientos armamos (ya viene predefinido) el contenido.
No tienes tiempo?  Completa los cursos cuando tu puedas…
No sabes por dende empezar? definite en que estado actual estas y selecciona el track que mas te ayude…
Pero esto no es solo aprendizaje, también al final, en nuestra graduación 😉 tenemos importantes «descuentos»

 

image

Los premios (un valor para tu esfuerzo), que vienen de la mano de descuento en certificaciones o cursos de e-learning…

 

 

Especialmente diseñado en base nuestras habilidades actuales (para no aburrir con el contenido).
Si eres un aspirante a desarrollador (principiante), ya tienes conocimientos en Java, VB6 o incluso .NET 2002/2003… tienes un programa especial

image

 

Utilizando laboratorios y cursos que teníamos disponible en www.microsoftelearning.com, nos guía en adquirir nuevas habilidades….

image

 

Ejemplo del track para los que están con VB6 y quieren empezar «El camino de la fuerza…»

image