Mostrando entradas con la etiqueta Combos. Mostrar todas las entradas
Mostrando entradas con la etiqueta Combos. Mostrar todas las entradas

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í.

miércoles, 27 de enero de 2010

Linq to Entities. Alias de columnas para un DropDownMenu

Los cambios siempre estresan. Y el cambiar de un ADO.NET en T-SQL a Linq to Entities me está produciendo algún que otro ardor de estómago.

Es el caso en el que quiero mostrar el nombre y apellidos en un DropDownMenu de ASP.net. Y en mi antigua cadena SQL lo que hacia era:

"SELECT idPersona, idNombre + " " + idApellido1 + " " + idApellido2 AS Persona FROM Personas"

Pero ahora en LinQ es una de esas cosas que buscas y rebuscas por Google y nada. ¿Porqué? Porque es tan sencillo que es muy difícil encontrarlo:

var db = new PruebasModel.PruebasEntities();
var losVehiculos = db.Vehiculo;
var resultado = from vehiculo in losVehiculos
select new{vehiculo.idVehiculo, persona = vehiculo.matricula + " " + vehiculo.matricula};

Ya solo me queda meterlo como dataSource de mi combo y voala!!.
DropDownList1.DataSource = resultado;
DropDownList1.DataValueField = "idVehiculo";
DropDownList1.DataTextField = "persona";
DropDownList1.DataBind();

miércoles, 16 de abril de 2008

Combos, siempre hay algo mejor.

No soy nada dado a utilizar material de otros lugares, pero esta entrada de José Manuel Alarcón en su blog merece la pena ser enlazado.

http://www.jasoft.org/blog/PermaLink,guid,686983f1-9881-43b2-a28f-0f9f54c62148.aspx

Si hubiera sabido está propiedad antes, unas cuantas cientos de líneas me hubiera ahorrado en estos útimos años.

viernes, 4 de enero de 2008

dataValueField y dataTextField, la potencia de la sencillez.

Bueno, esto es una mini entrada sobre una pequeña capacidad que tienen los controles tipo dropDownList, entre nosotros menús desplegables, que se trata de poderle decir qué campos del origen de datos vamos a utilizar para rellenarlo (Bind).

Veamos el ejemplo y luego lo analizamos:

dropDownList.DataSource = dataTable
dropDownList.DataValueField = "campo1"
dropDownList.DataTextField = "campo2"
dropDownList.DataBind()

Primero tenemos definido un control tipo combo llamado dropDownList y seleccionamos la tabla dataTable como la fuente de datos.

El truco del almendruco viene a continuación, ya que puedo indicarle por medio del nombre del campo de la tabla, cual quiero que sea el que se use para el value y cual para el texto visible.

¿Qué tiene esto de interesante? Pues así a bote pronto puedo traerme una tabla con 50 campos y utilizarla para rellenar diferentes combos al poder definir que columnas usar para cada uno. Lo cual también me lleva a que si lo introduzco en un SELECT CASE, puedo poblar el combo de manera condicional o, incluso de manera aún más interactiva, que se rellenen los menús de acuerdo a eventos de usuario. O, liandola más, que pueda seleccionar más de un value en cada combo (sincronizando la selección con la tabla).

Una capacidad sencillita pero que descarga mucho las llamadas a la base de datos y mejora la dura vida del programador.

P.D. No debería, pero recordaré que un dropDownList no es más que un control .NET que genera el código html tal cual el siguiente:

<.select>
<.option value="value">text
<./select>


En donde se observa en donde se representan cada uno de los dos valores antes mencionados.