Personal Website

My Web: MindEchoes.com

Wednesday, April 8, 2009

Como Filtrar un ComboBox WPF

Esta es una solución bastante simple pero MUY practica para el filtrado de un ComboBox en WPF dinamicamente mientras la persona va ingresando el texto:

Primero creamos una clase que puede llamarse "Util" que contendra un 1 atributo y 2 metodos todos estaticos.

Código de la Clase "Util":

Codigo fuente

using System;
using System.Collections.Generic;

namespace Project.util
{
public class Util
{

private static string Prefix = "";

private static bool StartWithPrefix(String s)
{
if (Util.Prefix.ToLower().Equals(""))
{
return true;
}
else if (s.ToLower().StartsWith(Util.Prefix.ToLower()))
{
return true;
}
else
{
return false;
}
}

public static void FilterCombo(
System.Windows.Controls.ComboBox combo, List<string> list)
{
Util.Prefix = combo.Text;

List<string> listFind = list.FindAll(
Util.StartWithPrefix);
combo.ItemsSource = listFind;

}

}
}


Para usar el filtro lo que hacemos es invocar el metodo FilterCombo de la clase Util pasandole como parametros el ComboBox al que deseamos aplicar el filtro, y una Lista de strings que es el contenido de nuestro Combo (es decir, la colección que asignamos en el ItemsSource del combo).

Una vez que tenemos nuestra clase Util lista, lo unico que tenemos que hacer es asignar en nuestra Interfaz de Usuario (Sea un control, ventana, etc) el ComboBox y colocarle las siguientes propiedades:
  • IsEditable = true;
  • IsTextSearchEnabled = false;
  • StaysOpenOnEdit = true;
Estas caracteristicas se puede editar desde el diseñador de interfaz o desde el xaml:

Codigo fuente

<ComboBox IsEditable="True" IsTextSearchEnabled="False"
StaysOpenOnEdit="True" KeyUp="comboBarrio_KeyUp" />


Una vez que tenemos nuestra Clase con los metodos estaticos, y nuestro ComboBox seteado, creamos un metodo para manejar el evento de KeyUp de nuestro ComboBox con el siguiente codigo:

Codigo fuente

private void combo_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key != System.Windows.Input.Key.Escape &&
e.Key != System.Windows.Input.Key.Down &&
e.Key != System.Windows.Input.Key.Up &&
e.Key != System.Windows.Input.Key.Left &&
e.Key != System.Windows.Input.Key.Right &&
e.Key != System.Windows.Input.Key.Enter)
{

this.combo.IsDropDownOpen = true;

Util.FilterCombo(this.combo, list);
}
}


De esta forma, lo que lograremos es que al situarnos sobre nuestro ComboBox y empezar a tipear algun caracter, el ComboBox se desplegara automaticamente y mientras vayamos tipeando nos filtrara la lista de resultados mostrando aquellos que comiencen con el prefijo que vamos ingresando.

El IF en el metodo "combo_KeyUp" lo que permite es que con "Esc" se cierre, con "Enter" nos deje seleccionar la opción sin que se vuelva a abrir el combo, y que podamos navegar entre las opciones filtradas con los flechas del teclado.

El hecho de que se haya expuesto la Clase "Util" con metodos estaticos es simplemente por el hecho de que sea posible llamarla desde cualquier clase de nuestro proyecto para poder ser utilizada en cualquier combo.




Eso es todo... cualquier consulta o mejora se aceptan comentarios :)

3 comments:

Anonymous said...

muy bueno che ahora lo puebo, gracias

fozziepupus said...

Muy buen ejemplo compañero, pero tengo una duda, ¿la lista que se le envía como parámetro, es la lista de datos que llena el combobox? y ¿está lista la creas y la asignas al combo en el KeyUp o desde dónde? porque seguí tu ejemplo pero yo cree una lista, y cree un método donde hago una consulta con linq a una tabla de base de datos y el resultado de esa consulta se lo agrego a la lista y la lista la agrego al combo, y este método lo llamo en el constructor, entonces esta lista es la que envió como parámetro pero no me funciona bien, porque tecleo en el combobox y hace el filtro pero borra lo que tecleo... espero me explique, gracias y espero tu respuesta ;)

//método que llamo en el constructor
public void llenaCombo() {

var x = from p in conex.Empleado select p;

foreach (Empleado w in x)
{
l.Add(w.nombre);
cbox.ItemsSource = l;
}
}

//evento keyUp
if (e.Key !=System.Windows.Input.Key.Escape && e.Key != System.Windows.Input.Key.Down &&
e.Key != ystem.Windows.Input.Key.Up && e.Key != System.Windows.Input.Key.Left && e.Key != System.Windows.Input.Key.Right && e.Key != System.Windows.Input.Key.Enter)
{
this.cbox.IsDropDownOpen = true;
Util.filtroCombo(this.cbox, l);

}

Diego Sarmentero said...

La verdad hace años que no programo ni con .net ni wpf... asi que no me acuerdo mucho...

si tuviera que decirte algo seria: no uses eso! Jeje
y te recomendaria python y qt