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
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)
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
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:
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:
-
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:
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:
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 :
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:
Descargar demo
(es una pagina con codebehind)
Enlaces:
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)
El resultado:
El resultado:
También aquí puedes leer otro articulo: Simple pero poderozo: Literal webcontrol
Resultado:
Esto quiere decir que nos ayuda a escribir contenido formateado para HTML
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:
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í:
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:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFIG\machine.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:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers
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.NET\Framework\{version}\CONFIG\Browsers) 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.NET\Framework\v2.0.50727\CONFIG\Browsers\mozilla.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