<p>Hola. Me gusta gnu linux para programar, no windows, y por eso estoy aprendiendo algo de gtk# basándome en lo que aprendí con window form en la utn para poder usar monodevelop en mint.</p>
<p>Bien, sucede que para escribir una grilla de datos nosotros usábamos , me parece, a system.window.forms.datagrid para escribir los datos y se enlazaba al dataset con la propiedad datasource. en gtk# se usa treeview con listview para hacer algo igual, pero uno necesita crear columna por columna y hay mucha más teoría para aprender. Resulta que hay 2 formas para hacer un listado de grilla (ignorando el tema de toma de datos de la bd porque eso funciona en mi programa) una es instanciando columna por columna, modificando su propiedad title, instanciando los procesadores de celda de clase CellRenderer (en mi caso cellrenderertext ya que solo mostrará texto) y con el método PackStart asignarle cada procesador de celda a una celda específica, por último, con el método appendcolumn se añade la columna al treeview correspondiente; lo cual como se ve acá es bastante feo de hacer (sobretodo para un programa que muestra 12 columnas en la grilla). Entonces, en la <a href="http://www.mono-project.com/GtkSharp_TreeView_Tutorial">documentación</a> explica el uso de un método sobrecargado de clase Gtk.Treeview.AppendColumn (el mismo que el anterior) pero que toma como parámetros el nombre de columna, una instancia de tipo CellRenderer(text|toggle|progress|etc), luego el tipo como cadena de caracteres y por último el número de columna que le corresponde, algo bien fácil de hacer (en la página de documentación, en el apartado escribir menos código).</p>
<p>Estos son 2 ejemplos en donde muestro , primero la primer sobrecarga de appendcolumn y la segunda para mostrar la ventaja de la que uso yo:</p>
<p>sobrecarga1: <a href="http://pastebin.com/gwUBUNhE">http://pastebin.com/gwUBUNhE</a></p>
<pre class="prettyprint"> grilla_de_datos_de_los_clientes = new TreeView();
TreeViewColumn col1 = new TreeViewColumn(); TreeViewColumn col2 = new TreeViewColumn();
CellRendererText proc_cel1 = new CellrendererText(); CellRendererText proc_cel2 = new CellrendererText();
col1.title = "columna1"; col2.title = "columna2";
proc_cel1.editable = proc_cel2.editable = true;
col1.packstart(proc_cel1, true); col2.packstart(proc_cel2, true)
grilla_de_datos_de_los_clientes.appendcolumn (col1); grilla_de_datos_de_los_clientes.appendcolumn (col2);
// el tipo de dato de cada columna ListStore modelo_de_lista_de_clientes = modelo_de_lista_de_clientes = new ListStore (typeof(String), typeof(String));
<y más código que comparten ambas sobrecargas></pre>
<p> </p>
<p>sobrecarga2: <a href="http://pastebin.com/7QxEA2aL">http://pastebin.com/7QxEA2aL</a></p>
<pre class="prettyprint"> grilla_de_datos_de_los_clientes = new TreeView();
// el tipo de dato de cada columna ListStore modelo_de_lista_de_clientes = modelo_de_lista_de_clientes = new ListStore (typeof(String), typeof(String));
grilla_de_datos_de_los_clientes.appendcolumn ("columna1", new CellRendererText(), "text", 0); grilla_de_datos_de_los_clientes.appendcolumn ("columna2", new CellRenderText(), "text", 1);
<y más código que comparten ambas sobrecargas></pre>
<p>El problema es el siguiente, yo necesito que las celdas sean editables; la documentación menciona que hay que poner a true la propiedad editable del procesador de celdas (como se muestra en el primer ejemplo), pero en la segunda sobrecarga no sé cómo acceder a la instancia del cellrenderertext, por lo tanto lo que hago es</p>
<pre class="prettyprint"> / por cada columna, por cada procesador de celdas, poner su propiedad editable en true /
for (int col=0; col<grilla_de_datos_de_los_clientes.Columns.Length; col++) { for (int proc=0; proc<grilla_de_datos_de_los_clientes.Columns[col].CellRenderers.Length; proc++) { grilla_de_datos_de_los_clientes.Columns[col].CellRenderers[proc].Editable = true <etc></pre>
<p> </p><p>lo que teóricamente, como muestra el ejemplo, funcionaría, pero monodevelop al compilar da error. Buscando en el depurador, tranquilamente puedo acceder a grilla_de_datos_de_los_clientes.Columns[col].CellRenderers[proc].Editable y tranquilamente la pongo en true en tiempo de ejecución y funciona ¿pero porqué no me lo toma en tiempo de diseño y compilación?</p>
<p> </p>
<p>Voy a lo importante, ¿cómo accedo a la instancia de CellRendererText de la segunda sobrecarga si no tiene identificador para poner su propiedad editable en true? y también algo curioso ¿porqué puedo modificar esa propiedad editable y funciona en tiempo de ejecución, mientras que escribiendo el código ni en el autocompletado ni al compilar funciona?</p>
<p> </p>
<p>Gracias por todo! </p>
<p>Lamentablemente hacer esto con GTK al principio resulta bastante tedioso. No soy programador de windows, pero reconozco que en Visual Studio es mucho más sencillo.</p>
<p>Vamos al problema. Lo que estás haciendo está bien, pero lo que ocurre es que al hacer esto:</p>
<pre class="prettyprint"> grilla_de_datos_de_los_clientes.Columns[ col ].CellRenderers[ proc ]</pre>
<p>Estas accediendo a un <strong>CellRenderer</strong> y no a un <strong>CellRendererText</strong> ( que hereda de la anterior ). La propiedad <strong>Editable</strong> existe en <strong>CellRendererText</strong> pero no en <strong>CellRenderer</strong>. Por eso la forma correcta de hacerlo en tu código sería haciendo un cast de la siguiente forma:</p>
<pre class="prettyprint"> for( int columna = 0; columna < tree.Columns.Length; columna++ ) { for( int celda = 0; celda < tree.Columns[ columna ].CellRenderers.Length; celda++ ) { // Se hace un CAST, de CellRenderer a CellRendererText CellRendererText celda_editable = ( CellRendererText ) tree.Columns[ columna ].CellRenderers[ celda ]; celda_editable.Editable = true; // Ahora sí funciona } }</pre>
<p>Entonces, contestando a tu pregunta:</p>
<blockquote> <p><span style="color:rgb(68,68,68);font-size:14px;">¿porqué puedo modificar esa propiedad editable y funciona en tiempo de ejecución, mientras que escribiendo el código ni en el autocompletado ni al compilar funciona?</span></p> </blockquote>
<p>Lo más probable es que al depurarlo estés tomando esa variable como CellRendererText, lo cual sí funciona.</p>
<hr /><p>Esto depende de tu código completo pero posiblemente una forma más sencilla de hacerlo sea poniendo Editable = true antes de utilizar el método appendColumn, como muestro en este código:</p>
<pre class="prettyprint"> CellRendererText celda1 = new CellRendererText( ); CellRendererText celda2 = new CellRendererText( ); celda1.Editable = celda2.Editable = true; tree.AppendColumn( "Columna 1", celda1, "text", 0 ); tree.AppendColumn( "Columna 2", celda2, "text", 1 );</pre>
<hr /><p>Pero si tenés 12 columnas como decís y tu intención es que el código sea más sencillo y corto, lo ideal ( para mi ) es que hagas una clase propia que herede de Gtk.TreeView. Luego podés crear tu propio método en el cual agregar una nueva columna ( appendColumn ) pero que sea editable( appendEditableColumn ). Y todos los CellRenderer se maniuplarían dentro de dicha clase. Podría ser algo como lo siguiente:</p>
<pre class="prettyprint"> public class GridView : Gtk.TreeView {
/**
* Agrega una columna editable
*/
public Gtk.TreeViewColumn AppendEditableColumn( string title, Gtk.CellRendererText cell, params object[] attrs ){
cell.Editable = true;
return this.AppendColumn( title, cell, attrs );
}
}</pre>
<p><em>NOTA: No me gusta utilizar CamelCase para nombrar clases/métodos/etc, siempre prefiero el guión bajo, pero lo escribo así simplemente para que coincida con la notación de GTK.</em></p>
<p>Luego lo utilizarías de la siguiente forma:</p>
<pre class="prettyprint"> GridView grid = new GridView(); grid.AppendEditableColumn( "Columna 1 ( editable )", new CellRendererText(), "text", 0 ); grid.AppendColumn( "Columna 2", new CellRendererText(), "text", 1 );</pre>
<p> </p>
<p>Espero te sirva. Saludos!!</p>
<p> </p>
<p>Edito:</p>
<p>Por nada! Me alegro mucho que te haya funcionado! y también que uses el guión bajo! ;) Un saludo Lucas!</p>
<p>muchas gracias Oláz por tomarte tu tiempo para responderme esta cuestión de forma tan detallada :) ¡funciona! . También yo uso guión bajo, es más sencillo y más gratificante ver un código escrito con él en lugar de mayúsculas.</p>
<p>Nuevamente muchas gracias, saludos!</p>