Llenar un Gtk.TreeView con MySQL
Tratando de ir extendiendo el tema de la conexión
con MySQL
ya empezamos a entrar en territorio más especifico, y en
este artículo intentaré explicar por medio de un
ejemplo como podemos tomar las filas devueltas por una consulta de
MySQL a un Gtk.TreeView, tratando de emular
un "DataGrid".
También podremos capturar el ID de la fila seleccionada en
un Gtk.Entry.Este artículo es una extensión de "Conectar a MySQL con MonoDevelop", por lo tanto, me saltaré todo el tema de conexión.
Primero que nada, vamos a crear la tabla que vamos a usar para este ejemplo, en una base de datos llamada "prueba".
-- -- Estructura de tabla para la tabla `usuarios` -- DROP TABLE IF EXISTS `usuarios`; CREATE TABLE `usuarios` ( `id` int(11) NOT NULL auto_increment, `nombre` varchar(150) NOT NULL, `apellidos` varchar(200) NOT NULL, `telefono` varchar(100) NOT NULL, `ciudad` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) TYPE=MyISAM AUTO_INCREMENT=3 COMMENT='Tabla de Usuarios' AUTO_INCREMENT=3 ; -- -- Volcar la base de datos para la tabla `usuarios` -- INSERT INTO `usuarios` VALUES (1, 'Alejandro', 'Garcia', '111-1111111', 'Puebla'); INSERT INTO `usuarios` VALUES (2, 'Carlos', 'Lopez', '222-2222222', 'D.F.');
y agregamos un nuevo usuario llamado "mono" con contraseña "develop" que tenga acceso total a la base de datos "prueba". (En caso de no tenerlo anteriormente).
Ahora es momento de crear nuestro nuevo proyecto Gtk#, como siempre desde el menú "Archivo" en la opción "Nuevo Proyecto...". (Estoy usando la versión 0.12 de MonoDevelop para el desarrollo de este ejemplo).
Les recuerdo que al final del presente artículo se encuentran todos los archivos usados en este proyecto listos para su descarga.
Para este proyecto vamos necesitar usar únicamente dos Widgets; un Gtk.TreeView, que es donde se llenarán las filas de datos, y un Gtk.Entry, que es donde veremos que fila hemos seleccionado en el TreeView, por lo tanto el formulario quedaría más o menos así:
Con las siguientes propiedades.
Gtk.TreeView
Nombre del widget: "treeviewData"
Gtk.Entry
Nombre del widget: "entrySeleccionado"
isEditable: No seleccionado
No hay que olvidar seleccionar cada uno de los Widgets y pulsar sobre el botón "Bind to Field", para que sean declarados en el código fuente.
Ya por último en el diseño del formulario, solo nos queda seleccionar el TreeView y en las "Propiedades del componente" dar de alta la señal "CursorChanged" dándole un nombre al Handler como por ejemplo "treeviewData_cursorChanged", para que posteriormente podamos detectar el ID de alguna fila seleccionada.
Ya es momento de empezar a escribir algo de código, así que para empezar, debemos de realizar la conexión con MySQL, punto que ha quedado explicado en el artículo anterior "Conectar a MySQL con MonoDevelop".
Antes de continuar, quiero recomendar ampliamente leer el manual "TreeView for Kids", o en español "TreeView para niños", el cual fue traducido por Daniel Valcarce, y también poner especial atención en estudiar la versión ampliada que nos proporciona Mono Hispano de TreeView para niños, donde podremos conocer mucho más a detalle de lo que yo puedo, la naturaleza y funcionamiento de este Widget.
Lo primero es crear las columnas de las que se compondrá nuestro listado, en este caso, y basado en nuestra tabla de mysql, estoy pensando en incluir todos los campos (id, nombre, apellidos, telefono, ciudad). Para este efecto usaremos el método "Gtk.TreeView.AppendColumn", quien como su nombre indica, agrega una nueva columna a nuestro TreeView, en este caso vamos agregar 5 columnas de la siguiente forma.
// Se agregan las columnas al treeview treeviewData.AppendColumn("ID", new Gtk.CellRendererText(), "text", 0); treeviewData.AppendColumn("Nombre", new Gtk.CellRendererText(), "text", 1); treeviewData.AppendColumn("Apellidos", new Gtk.CellRendererText(), "text", 2); treeviewData.AppendColumn("Telefono", new Gtk.CellRendererText(), "text", 3); treeviewData.AppendColumn("Ciudad", new Gtk.CellRendererText(), "text", 4);
- El primer parámetro es el nombre que nosotros le asignamos a la columna.
- El segundo parámetro es un Gtk.CellRenderer, el cual se encarga de manejar la visualización de los datos de cada celda dentro de un TreeView. Existen 3 tipos de CellRenderer: Gtk.CellRendererText, el cual se usa para mostrar solo texto, Gtk.CellRendererPixBuf para el manejo de imágenes y Gtk.CellRendererToggle, con el cual lograremos mostrar un CheckBox, que seguramente nos será de mucha utilidad en campos booleanos.
- El tercer parámetro es un conjunto de atributos para el tipo de visualización para la columna, donde podemos seleccionar entre tres valores: "text", "pixbuf" y "markup".
- El cuarto parámetro, es el orden de identificación de las columnas.
Debemos tener muy en cuenta que el Widget TreeView incorpora un patrón MVC, por lo tanto el CellRenderer corresponde al "View".
Retomando el ejemplo que nos concierne, la columna del ID solo la quiero usar para el manejo interno de listado, por lo que la podemos ocultar modificando su visibilidad.
// Oculto la columna del ID treeviewData.Columns[0].Visible = false;
Ahora es necesario crear el modelo (Model del MVC), usando Gtk.ListStore. Como se puede ver, corresponde a las 5 columnas usadas y se le declara el tipo de datos que se va a usar, para después asignarlo al TreeView de la siguiente forma:
// Se crea el modelo Gtk.ListStore clientesListStore = new Gtk.ListStore (typeof(int), typeof(string), typeof(string), typeof(string), typeof(string)); // Se asigna el modelo al treeview treeviewData.Model = clientesListStore;
Conectando a MySQL justo como el artículo pasado, y dentro del while, podemos empezar a llenar nuestro TreeView de una forma realmente fácil usando el método Gtk.ListStore.AppendValues, y como el modelo ya se encuentra conectado, el CellRenderer empieza a realizar su trabajo mostrando cada una de las filas.
clientesListStore.AppendValues(myReader["id"], myReader["nombre"].ToString(), myReader["apellidos"].ToString(), myReader["telefono"].ToString(), myReader["ciudad"].ToString());
El siguiente objetivo es poder detectar el ID de una fila de datos seleccionada, para ello usaremos el handler "treeviewData_CursorChanged", incluyendo el siguiente código.
Gtk.TreeModel model; Gtk.TreeIter iter; if (treeviewData.Selection.GetSelected(out model, out iter)) { entrySeleccionado.Text = "ID Seleccionado: " + model.GetValue(iter, 0).ToString(); }
La idea, aunque algo enredada, es simple, Gtk.TreeView.Selection.GetSelected, nos va a entregar tanto el modelo, como la fila seleccionada, para después poder sacar el valor de la columna.
El código completo quedaría de la siguiente forma
using System; using Gtk; // Se agregan las referencias necesarias para conectar a la DB using System.Data; using MySql.Data.MySqlClient; public class MainWindow: Gtk.Window { protected Gtk.TreeView treeviewData; protected Gtk.Entry entrySeleccionado; public MainWindow (): base ("") { Stetic.Gui.Build (this, typeof(MainWindow)); // Se agregan las columnas al treeview treeviewData.AppendColumn("ID", new Gtk.CellRendererText(), "text", 0); treeviewData.AppendColumn("Nombre", new Gtk.CellRendererText(), "text", 1); treeviewData.AppendColumn("Apellidos", new Gtk.CellRendererText(), "text", 2); treeviewData.AppendColumn("Telefono", new Gtk.CellRendererText(), "text", 3); treeviewData.AppendColumn("Ciudad", new Gtk.CellRendererText(), "text", 4); // Oculto la columna del ID treeviewData.Columns[0].Visible = false; // Se crea el modelo Gtk.ListStore clientesListStore = new Gtk.ListStore (typeof(int), typeof(string), typeof(string), typeof(string), typeof(string)); // Se asigna el modelo al treeview treeviewData.Model = clientesListStore; // Cadena de Conexion a la DB string connectionString = "Server=localhost;" + "Database=prueba;" + "User ID=mono;" + "Password=develop;" + "Pooling=false"; // Query para extraer la informacion de la tabla string myQuery = "SELECT id, nombre, apellidos, telefono, ciudad FROM usuarios;"; // Se crea el objeto de conexion MySqlConnection myConnection = new MySqlConnection(connectionString); try { // Abre la conexion myConnection.Open(); // Crea el objeto de ejecucion del query MySqlCommand myCommand = new MySqlCommand(myQuery, myConnection); // Ejecuta el query MySqlDataReader myReader = myCommand.ExecuteReader(); // Lee cada uno de los registros devueltos while (myReader.Read()) { // Se agrega una linea al treeview clientesListStore.AppendValues(myReader["id"], myReader["nombre"].ToString(), myReader["apellidos"].ToString(), myReader["telefono"].ToString(), myReader["ciudad"].ToString()); Console.WriteLine("ID: " + myReader["id"].ToString()); } // Se cierra el reader myReader.Close(); // Se cierra la conexion con la DB myConnection.Close(); } catch(Exception myError) { // En caso de algun error lo veremos en la consola de depuracion Console.WriteLine(myError.ToString()); } } protected void OnDeleteEvent (object sender, DeleteEventArgs a) { Application.Quit (); a.RetVal = true; } protected virtual void treeviewData_CursorChanged(object sender, System.EventArgs e) { Gtk.TreeModel model; Gtk.TreeIter iter; if (treeviewData.Selection.GetSelected(out model, out iter)) { entrySeleccionado.Text = "ID Seleccionado: " + model.GetValue(iter, 0).ToString(); } } }
Llegó la hora de ejecutar el proyecto.
Por el momento eso es todo, espero que este artículo sea de utilidad. Saludos.
El proyecto y código relacionado a este artículo, están disponibles en los siguientes archivos.
| Adjunto | Tamaño |
|---|---|
| MySQLTreeView.tar.gz | 5.66 KB |
| prueba.sql.gz | 557 bytes |
![]() |
hola, (slnMySqlTreeView:8630): Gtk-WARNING **: /build/buildd/gtk+2.0-2.12.9/gtk/gtkliststore.c:608: Unable to convert from guint to gint ID: 1 (slnMySqlTreeView:8630): Gtk-WARNING **: /build/buildd/gtk+2.0-2.12.9/gtk/gtkliststore.c:608: Unable to convert from guint to gint ID: 2 y en el treeview la columna Id me aparece con valor cero, y ademas cambia de nombre,por ejemplo en la BD el campo es "id" y en treeview aparece :"ID", pero, como repito, con valort cero. A que se deberá esto...el codigo no lo he cambiado todo esta igual.. Gracias. |
![]() |
Hola, yo escribi acerca de unos errores que me daban, bueno he preguntado en el canal irc #mono y me han dado la respuesta : copio esto por si acaso le sirve a alguien |
![]() |
Hola, |
![]() |
void creacion_del_combobox(int tipocombobox, string solicitadopor, string concargoa) { idtipointernamiento = idcentrocosto; // Llenado de combobox1 combobox_tipo_admision.Clear(); CellRendererText cell1 = new CellRendererText(); combobox_tipo_admision.PackStart(cell1, true); combobox_tipo_admision.AddAttribute(cell1,"text",0); ListStore store1 = new ListStore( typeof (string), typeof (int)); combobox_tipo_admision.Model = store1; combobox_tipo_admision2.Clear(); CellRendererText cell2 = new CellRendererText(); combobox_tipo_admision2.PackStart(cell2, true); combobox_tipo_admision2.AddAttribute(cell2,"text",0); ListStore store2 = new ListStore( typeof (string), typeof (int)); combobox_tipo_admision2.Model = store2; string accesocentrocosto = ""; bool primero = true; if(tipocombobox == 1){ foreach (int i in this.array_idtipoadmisiones){ if (primero == true){ accesocentrocosto = i.ToString(); primero = false; }else{ accesocentrocosto = accesocentrocosto + "','"+i.ToString(); } } // lleno de la tabla de his_tipo_de_admisiones NpgsqlConnection conexion; conexion = new NpgsqlConnection (connectionString+nombrebd); // Verifica que la base de datos este conectada try{ conexion.Open (); NpgsqlCommand comando; comando = conexion.CreateCommand (); comando.CommandText = "SELECT * FROM hscmty_his_tipo_admisiones "+ "WHERE id_tipo_admisiones IN('"+accesocentrocosto+"')"+ "ORDER BY descripcion_admisiones;"; NpgsqlDataReader lector = comando.ExecuteReader (); while (lector.Read()){ if((int) lector["id_tipo_admisiones"] == idtipointernamiento){ store1.AppendValues ((string) lector["descripcion_admisiones"], (int) lector["id_tipo_admisiones"]); } store2.AppendValues ((string) lector["descripcion_admisiones"], (int) lector["id_tipo_admisiones"]); } }catch (NpgsqlException ex){ MessageDialog msgBoxError = new MessageDialog (MyWinError,DialogFlags.DestroyWithParent, MessageType.Error,ButtonsType.Close,"PostgresSQL error: {0}",ex.Message); msgBoxError.Run (); msgBoxError.Destroy(); } conexion.Close (); }else{ store1.AppendValues ((string) solicitadopor,0); store2.AppendValues ((string) concargoa,0); } TreeIter iter1; if (store1.GetIterFirst(out iter1)){ //Console.WriteLine(iter2); combobox_tipo_admision.SetActiveIter (iter1); } TreeIter iter2; if (store2.GetIterFirst(out iter2)){ //Console.WriteLine(iter2); combobox_tipo_admision2.SetActiveIter (iter2); } combobox_tipo_admision.Changed += new EventHandler (onComboBoxChanged_tipo_admision); combobox_tipo_admision2.Changed += new EventHandler (onComboBoxChanged_tipo_admision2); // fin de llenado de los combobox } |
![]() |
un buen tuto en español probadoo y funciona al 100 gracias |




Felicitaciones por la pagina y gracias por este ejemplo.
Podrias, porfavor, hacer lo mismo pero con un combo box
gracias!!