viernes, 13 de agosto de 2010

ASP.NET MVC + JQuery

He empezado a empaparme del desarrollo con ASP.NET MVC, haciendo el tutorial básico de MSDN y escuchando una extensa presentación en ALT.NET.

Tiene buena pinta la cosa, y vamos a probar a qué sabe.

lunes, 9 de agosto de 2010

UpdatePanel desde un control de usuario

Pequeño problemilla que se resuelve de forma sencilla.
Tengo un GridView dentro de un UpdatePanel y quiero actualizarlo cuando:
  • Pulso un botón en la propia Página que contiene el GridView.
  • Pulso un botón que está situado en un control de usuario.
<%@ Register TagPrefix="CU" TagName="ControlUsuario" Src="~/controles/CU.ascx" %>
<asp:UpdatePanel ID="UpdatePanelGvAsignaciones" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:GridView ID="gvAsignaciones" runat="server" AutoGenerateColumns="true">
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="bBotonEnPagina" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<CU:ControlUsuarioID="ControlUsuario" runat="server" />
El primer requisito es fácil, declaro un trigger y listo.

Para el segundo requisito, tengo en cuenta que para poder lanzar el evento onClick del botón del control de usuario dentro de la página principal tengo que suscribir un método de la misma al evento correspondiente.
ControlUsuario.bBotonEnControlUsuario_Click += aceptarEnControlUsuario;
Y dentro del método que se lanza, actualizo el UpdatePanel que contiene el GridView.
public void aceptarEnControlUsuario()
{
  UpdatePanelGvAsignaciones.Update();
}
Y ya está!!

jueves, 5 de agosto de 2010

La muerte de Google Wave

No sé si aplaudir o criticar la decisión de Google de cerrar su “invento”. Lo que si tengo claro que solamente los que se equivocan son los que innovan y Google demuestra su valía continuadamente con la búsqueda constante de encontrar nuevas vías y maneras de vivir la comunicación en Internet.

No todo puede salir bien, y estaba claro desde el primer momento que Wave no era lo que se necesitaba en ese momento o era (mi parecer) algo amorfo que no entregaba más valor de lo que ya existía y además te insertaba en  un ecosistema cerrado.

No lamento la muerte de Wave. Lo eliminé al primer día de su uso. Y espero que este revés no afecte a la fantástica política de innovación de Google.

lunes, 2 de agosto de 2010

Ajax.net: TextBox + DropDownList + Autocomplet con Text y Value

Me he encontrado con la necesidad de hacer un textbox para introducir nombre de calles y que, según fuera introduciendo letras, me fuera ofreciendo resultados de una búsqueda en la base de datos.

Lo primero que hice fue utilizar un extensor de Ajax.net Control Toolkit llamado AutoComplete. Pero se me presentó un problemón que es lo que me ha llevado a investigar y a publicar esta solución.

Las calles las busco por su nombre pero deben ser salvados por su identificador… lo cual es muy fácil en un dropDownList ya que tienes siempre el par (text, value). ¿Pero cómo lo hago con este extensor?

Pues lo primero es montar el extensor Autocomplete.

Osea por la parte del aspx tengo:

        <asp:TextBox ID="txtbVia" runat="server" Width="253px"></asp:TextBox>
<
asp:AutoCompleteExtender ID="txtbVia_AutoCompleteExtender" runat="server"
ServiceMethod="GetCompletionList"
TargetControlID="txtbVia"
UseContextKey="True"
CompletionInterval="0">
</
asp:AutoCompleteExtender>

En el codeBehind, primero debo hacer el include de la librería de servicios web y de colecciones:

using System.Collections.Generic;
using System.Web.Services;


Y el código del servicio web que me va a devolver el listado de calles. Que, aquí viene el primer “truco del almendruco”, nos permite incluir el par de texto y valor en el dropDownList a visualizar:



[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
public static string[] GetCompletionList(string prefixText, int count, string contextKey)
{
List<string> items = new List<string>();

foreach (Entidades.Calles calle in BL.CallesManager.GetCalleComboList(prefixText))
{
items.Add(AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(calle.nombre , calle.codvia.ToString()));
}

return items.ToArray();
}


Vamos a explicarlo un poquito más.

La firma del método es bastante rarita, pero lo más sencillo es entrar en modo split en el diseñador del fichero ascx, pulsar en las propiedades de la extensión y que el propio diseñador te haga el WebMethod pertinente. Como se ve en la firma, debemos devolver un array de strings, por eso declaro uno al principio del cuerpo del método y por eso hago un using a System.Collections.Generic.


A continuación nos traemos los datos de la base de datos. En este caso en LinQ me traigo un Iqueryable de objetos del tipo Calles el cual recorro con un foreach y… (atención aquí está el meollo del asunto) lo añado a mi lista de cadenas como un AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(tex, value)!!


¿A que mola? Pues esto lo encontré en el blog With Great Power comes Great Response.write('Ability'). Darle las gracias, que es el único en donde encontré algo legible o entendible.


Pero la cosa se complica, porque necesito poder capturar el valor del item seleccionado en el combo, y eso solamente lo puedo hacer en el lado del cliente… para lo cual añado un método javascript que me coja dicho valor y me lo cargue en un input field del tipo hidden para poder recuperarlo desde el code behind cuando pulse en el botón de guardar.


Primero añadamos un línea más al extensor para invocar al método javascript y pongamos el script.



<script type="text/javascript">
function
viaSeleccionada(source, eventArgs) {
//alert(" Key : " + eventArgs.get_text() + " Value : " + eventArgs.get_value());
document.getElementById('<%= lblIdVia.ClientID %>').innerText = eventArgs.get_value();
}
</script>

<
asp:UpdatePanel ID="UpdatePanelVia" runat="server" UpdateMode="Conditional">
<
ContentTemplate>
<
asp:TextBox ID="txtbVia" runat="server" Width="253px"></asp:TextBox>
<
asp:AutoCompleteExtender ID="txtbVia_AutoCompleteExtender" runat="server"
ServiceMethod="GetCompletionList"
TargetControlID="txtbVia"
UseContextKey="True"
CompletionInterval="0"
OnClientItemSelected="viaSeleccionada"> //ESTA LINEA ES NUEVA
</
asp:AutoCompleteExtender>
<input ID="lblIdVia" runat="server" type="hidden" />
</ContentTemplate>
</
asp:UpdatePanel>


Aquí debo señalar varias cosas:

1. La propiedad del extensor OnClietItemSelected, que se lanza en el cliente solamente.


2. La alerta que está comentada dentro del javascript que nos vale para poder  debuguear los valores que devuelve el DropDownList.


3. El input del tipo hidden pero declarado como runat=”server” que nos vale de puente entre el cliente y el servidor. Gracias a bendragon en este foro.


4. La forma de localizar este control desde Javascript con un getElementById, y el ClientID (que puede ser muy distinto del ID que escribimos nosotros) y la carga del valor a través del innerText.


Y ya tá. Tengo un textBox que, según voy escribiendo, me va devolviendo en un DropDownlist una lista de calles que incluyen las letras o palabras que he introducido y que, cuando selecciono una, me guarda el id de la calle seleccionada dentro de un campo oculto al que puedo acceder desde el code behind.


Espero que os sea tan útil como a mí.