UNIVERSIDAD DE CORDOBA FACULTAD DE INGENIERIAS PROGRAMA INGENIERIA DE SISTEMAS CURSO: Electiva de profundización I (desarrollo de software libre) TEMA: Archivos de texto en C#. DESCRIPCION: A lo largo de este documento se realiza un estudio del concepto y
características de los archivos de texto y la respectiva implementación de un ejemplo practi practico co en lengua lenguaje je C# median mediante te un proyec proyecto to de interf interfaz az grafic grafica a de usuari usuario o (GUI) (GUI) cons constr trui uido do con con Mono MonoDe Deve velo lop p basa basado do en GTK# GTK# 2.0, 2.0, desc descri ribi bien endo do adem ademas as los los ensamblados, clases y métodos de estas disponibles en C# para el tratamiento de archivos texto. Para este efecto se diseña e implementa una primera clase abstracta especializada en las operaciones de creación y apertura de un archivo de texto en modo de escritura, de tal suerte que además permita almacenar en disco (serializar) cualquier tipo de objeto mediante un método abstracto. En ese mismo orden de ideas se diseña e implementa una segunda clase para apertura y recorrido de un archivo de texto en modo de lectura, que además tiene un método abstracto para recuperar los objetos serializados en el archivo. El proyecto de ejemplo ilustra el uso de menus en GTK# 2.0 y cuadros de diálogos para la apertura y guardado guardado de archivos, archivos, adicional al uso de filtros filtros en estos para tipos de archivos. OBJETIVO: Diseñar e implementar en el lenguaje C# las clases necesarias para realizar
las operaciones de creación, apertura, escritura y lectura de archivos de texto, incluyendo la serializacion y recuperación de cualquier tipo de objetos, desarrollando para ello una aplicación de ventanas en C# con con MonoDevelop que muestre la serialización serialización de un tipo de objetos y su recuperación desde un archivo de texto. PALABRAS CLAVES : Archivos de texto en C#, serialización de objetos, la clase File,
StreamWriter y StreamReader de C#, los Widget TreeView y MenuBar.
Lic. Luis Roberto Olascoaga Surmay
1. Arch Archiv ivos os de Text Texto o
En general los archivos son un mecanismo de persistencia de datos aunque menos sofisticados como por ejemplo el caso de las bases de datos. Esto significa que los datos con que trabajan trabajan nuestros nuestros programas programas pueden pueden ser guardados guardados de manera permanente permanente en disco, de modo que en cualquier momento posterior lo podamos recuperar sin que se pierdan por causa de cerrar el programa o reiniciar nuestra PC. El tratamiento de un archivo podemos enfocarlo desde distintos puntos de vista, según si nos interesa realizar con ellos ellos operac operacion iones es propia propiass del sistem sistema a operat operativo ivo (como (como por ejempl ejemplo o copia copiado do,, renomb renombrad rado, o, asigna asignació ción n de permis permisos os,, elimin eliminaci ación ón etc.) etc.) en las que el signif significa icado do o interpretación del contenido del archivo no es de importancia. Por otro lado el trabajo con el archivo también puede orientarse hacia el tratamiento del contenido de este, lo cual incl incluy uye e oper operac acio ione ness como como la lect lectur ura, a, la escr escrititur ura a o modi modififica caci ción ón y en todo todo caso caso suponemos que interesa el significado significado o interpretación interpretación del contenido del archivo. archivo. En este documento trataremos a los archivos en función de su contenido. En cuanto a los archivos de texto, estos constituyen la forma más simple de guardar y leer datos hasta o desde un archivo físico en disco. Un archivo de texto, como su nombre lo indica, esta compuesto por un conjunto de líneas de caracteres, que se almacenan en el archivo usando algún formato especial de codificación, entre los que se destacan el ASCII, UNICODE, UTF entre otros. Estos valores se almacenan sin ningún atributo de texto especial como tamaño de letra, color y características similares, con lo cual a los archivos de texto también se les llaman archivos planos. Por estas razones el contenido de un archivo de texto es legible, lo cual supone que podemos ver y comprender su cont conten enid ido o dire direct ctam amen ente te,, al meno menoss desd desde e cual cualqu quie ierr edit editor or de text texto; o; incl inclus uso o con con independencia del sistema operativo, lenguaje de programación o software con el que se ha creado dicho archivo. En términos de las operaciones de lectura y escritura en archivos de texto, estas se hacen línea a línea, es decir que cada vez que se guarda o se lee se almacena o se lee una línea de caracteres completa, la cual puede variar para cualquiera de las dos operaciones en la longitud o cantidad de caracteres que la componen. Siempre que se guarda una línea o se lee, el puntero de archivo avanza a la siguiente línea, por lo cual un archivo de texto en función de su modo de acceso es también un archivo secuencial. Así por ejemplo si queremos acceder a la décima línea de un archivo, previamente debemos leer las nueve que le preceden. Las operaciones de lectura y de escritura en archivos de texto son Lic. Luis Roberto Olascoaga Surmay
mutuamente excluyentes, es decir, un archivo de texto se abre en un solo modo; sea para leer o para escribir y no en ambos; no obstante se puede abrir en un modo, realizar las operaciones requeridas y luego cerrarse para abrirse en el otro modo. 2. Arch Archiv ivos os de Tex Texto to en C#
Las consideraciones anteriormente expuestas aplican a la forma en la cual se ven los archivos de texto en el lenguaje C#. Para el tratamiento de archivos (de cualquier tipo) y de dire direct ctor orio io desd desde e C# se util utiliz iza a el ensa ensamb mbla lado do System.IO, que que contie contiene ne clases clases,, exce excepc pcio ione nes, s, estr estruc uctu tura ras, s, enum enumer erac acio ione ness y demá demáss elem elemen ento toss espe especi cial aliz izad ados os en operaciones de entrada y salida con archivos y directorios. Una de las clases más representativas de este ensamblado es la clase
File,
la cual contiene métodos estáticos
para gestión tanto de archivos como de directorios entre los que se destacan:
File.Copy File.Copy : Que permite hacer una copia exacta de un archivo dando el nombre del
archivo original y el nombre de la copia (destino).
File.Move File.Move: Que permite mover un archivo de un directorio o disco a otro, o en su
defecto renombrar un archivo existente. Es equivalente a la operación de cortar y pegar pegar y se le indican indican el nombre del del archivo archivo original original y el nuevo nombre o destino destino (directorio).
File.Delete File.Delete: Que borra físicamente un archivo dando el nombre del archivo.
File.Exitsts File.Exitsts: Función booleana que determina si un archivo o directorio existe o no,
indicando el nombre del archivo o directorio según sea el caso.
File.GetCreationTime: Función a la que se le indica un nombre de archivo o directorio
y retorna un tipo DateTime representativo de la fecha y hora en la que fue creado.
File.GetLastAccessTime: Función que toma por parámetro el nombre de un archivo y
retorna un tipo DateTime con la fecha y hora en la que el archivo fue accedido por ultima vez.
File.GetLastWriteTime: Función a la que se le pasa el nombre de un archivo y retorna
un tipo DateTime con la fecha y hora en la que el archivo fue modificado por última vez.
File.OpenText File.OpenText : Función que crea una instancia de la clase StreamReader usada para
leer un archivo de texto indicando el nombre del archivo, dejando el puntero de archivo en la primera línea del archivo. Lic. Luis Roberto Olascoaga Surmay
File.CreateText File.CreateText : Función que crea una instancia de la clase StreamWriter usada para
escribir en un archivo de texto indicando el nombre del archivo. Si el archivo no existe lo crea, pero si existe borra su contenido.
File.AppendText File.AppendText : Función que crea una instancia de la clase StreamWriter usada para
escribir en un archivo de texto en modo añadir al final, indicándole el nombre del archivo. Si el archivo no existe lo crea y si existe conserva su contenido. Ahora bien para acceder a un archivo de texto en modo de escritura optamos por usar la clase StreamWriter la cual tiene los siguientes métodos y propiedades de interés:
Write: Método sobrecargado para guardar un dato o valor de cualquier tipo hasta el
archivo, sin hacer un salto de línea en este después de almacenar el valor.
Write Wri te Line Lin e: Método sobrecargado para guardar un dato o valor de cualquier tipo hasta
el archivo almacenando un salto de línea después de almacenar el valor.
Flush: Método que vacía el buffer de archivo usado de modo que se garantiza que
todo todoss los los camb cambio ioss o escr escrititur uras as hech hechos os en el arch archiv ivo o a nive nivell de memo memori ria a sean sean efectivamente guardados en el archivo físico en disco.
Close: Método que cierra el archivo y todos los flujos de datos abiertos por este.
Dispose: Método destructor del objeto.
Encoding: Propiedad que es un objeto representativo del tipo o formato de codificación
del archivo. En cuanto al acceso de un archivo de texto en modo de lectura usamos una instancia de la clase StreamReader cuyos métodos y propiedades de mayor importancia son:
Read : Método sobrecargado para leer un carácter o un buffer (arreglo) de caracteres
desde el archivo.
Read Re ad Line Li ne : Método que lee y retorna la línea de caracteres actual en el archivo; si no
hay más líneas que leer (cuando se llega al final) retorna un null.
ReadToEnd : Método lee todo el contenido del archivo de una vez retornándolo en una
sola cadena de caracteres.
Close: Método que cierra el archivo y todos los flujos de datos abiertos por este.
Dispose: Método destructor del objeto.
Lic. Luis Roberto Olascoaga Surmay
CurrentEncoding: Propiedad que es un objeto representativo del tipo o formato de
codificación codificación con el que se abrió el archivo.
EndOfStre dOf Stream: am: Propiedad booleana que indica si se ha alcanzado el final del archivo o
no durante las operaciones de lectura.
BaseStream: Propiedad que es una instancia descendiente de la clase Stream (flujo o
secu secuen enci cia a de dato datoss o byte bytes) s) rela relaci cion onad ada a con con el fluj flujo o de dato datoss del del arch archiv ivo. o. 3.
Presentación ejemplo serialización de objetos con archivos de texto
A efectos del proceso de serialización consideraremos almacenar los datos básicos de una persona correspondiente al código, apellidos, nombres, edad, estrato y sexo, los cuales cuales serán serán repres represent entado adoss por propie propiedad dades es de la clase clase TPersona. Se diseñara e implementara una clase para guardar datos en forma de líneas de caracteres hasta un archiv archivo o de texto, texto, la cual cual conte contendr ndrá á un métod método o abstra abstracto cto llamad llamado o GuardarObj para serializar un objeto de cualquier clase, además de los habituales métodos para crear, añadir y cerrar un archivo de texto conociendo su nombre a través de una propiedad. A esta clase la llamaremos TEscritura y de ella heredara la clase TEscPersona, que se especializara en guardar o serializar un objeto de la clase TPersona, implementando para ello el método abstracto GuardarObj de su clase padre, de tal suerte que se guarde cada cada propiedad (atributo) del objeto TPersona en una línea independiente. De mane manera ra anál análog oga a tene tenemo moss la clas clase e TLectura, la cual cual será será una una clas clase e abst abstra ract cta a especializada en las operaciones de apertura, lectura, recorrido de un archivo de texto y cierre de este, cuyo nombre y ruta se especificara mediante una propiedad. Iincluye además métodos para leer una línea cada vez, verificar la condición de fin fin de archivo y por supuesto un método abstracto llamado LeerObj que permitirá recuperar un objeto de cualqu cualquier ier tipo tipo desde desde el archi archivo. vo. Para este este efecto efecto se diseñ diseña a e implem implement enta a la clase clase TLecPersona que se especializa en leer o recuperar el estado de un objeto de la clase TPersona, implementando para ello el método abstracto LeerObj de su clase ascendiente
con la idea de que cada propiedad (atributo) del objeto TPersona se lea desde una línea independiente del archivo.
Lic. Luis Roberto Olascoaga Surmay
4. Diseño de clases para para archivos de texto y serialización de objetos objetos
Seguidamente vemos el diagrama de clases UML con el diseño de las clases y las relaciones entre estas, en donde se aprecia una relación de dependencia de las clases TEscPersona y TLecPersona (clases dependientes) respecto a la clase TPersona (clase
independiente) ¿Por qué razon debe ser una relacion de dependencia?.
Lic. Luis Roberto Olascoaga Surmay
5. Creación de la solución
Para desarrollar desarrollar el programa programa de serializa serialización ción de objetos objetos de la clase clase TPersona mediante archivos de texto procedemos de la siguiente manera: a) Entrar en Monodevelop: Monodevelop: Aplicaciones + programación + Monodevelop
b) Crear una una nueva solución: solución: Archivo Archivo + nuevo nuevo + soluc solución. ión.
c) Enseguida se muestra muestra la siguiente ventana, en la que que seleccionamos el nodo nodo C# de la
lista lista de la izquierd izquierda, a, y de la lista lista del centro centro escogem escogemos os proyect proyecto o GTK#2 GTK#2.0 .0 para después escribir el nombre del proyecto que será archivo_texto. Opcionalmente con el botón examinar se puede especificar una carpeta distinta a la presentada por defecto para para guar guarda darr el proy proyec ecto to.. Así Así mism mismo o es opci opcion onal al marc marcar ar la crea creaci cion on de un subdirectorio por separado para la solución. Finalmente pulse el botón adelante.
Lic. Luis Roberto Olascoaga Surmay
d) Seguidamente vemos la ventana para añadir otros proyectos adicionales y opcionales
a la solución, tales como soporte GTK#, proyecto de traducción e integración con Unix. Para nuestro caso ninguna de estas opciones son necesarias y por ello no debe marcarlas. La imagen siguiente presenta estas opciones y en ella se aprecia una descripción de cada una de estas opciones.
La siguie siguiente nte pantal pantalla la muestr muestra a el estado estado inicia iniciall de la soluc solución ión,, observ observánd ándose ose en la izquierda el inspector de la solución solución y en lado derecho apreciamos el archivo principal del proyecto llamado Main.cs que contiene la clase principal MainClass. También vemos que Lic. Luis Roberto Olascoaga Surmay
el nombre de espacio archivo_tetxo (namespace) engloba la definición de la clase principal. Para nuestros propósitos no es necesario y por lo tanto borrelo incluyendo la primera primera llave de apertura y la ultima llave llave de cierre. En la implementaci implementación ón del método método estático Main tenemos el uso del ensamblado Gtk, el llamado de métodos del objeto global global implícito implícito Application, adem además ás de la crea creaci ción ón de una una inst instan anci cia a de la clas clase e MainWindow que representa la ventana principal.
Después de borrar el nombre de espacio el código debe quedar como sigue:
Lic. Luis Roberto Olascoaga Surmay
6. Creación de los archivos para implementación de las clases
a) Ahora cree un archivo nuevo para implementar la clase TPersona haciendo click derecho en el nombre de la solución y tomar la opción añadir + nuevo archivo:
b) En la ventana desplegada del panel de la izquierda seleccionamos la opción general y del panel central la opción clase vacía, asignando por nombre TPersona y luego haga click en el botón nuevo para crear el archivo .cs correspondiente como se aprecia en la siguiente imagen.
Lic. Luis Roberto Olascoaga Surmay
Para implementar esta clase borre el nombre de espacio (namespace) dentro del código y asegúrese que el código quede como sigue en donde vemos que esta clase solo declara propiedades correspondiente a características básicas de una persona y los objetos creados de esta clase son los que vamos a serializar:
using System; public class TPersona{ private int FCodigo; private string FApellidos; private string FNombres; private byte FEdad; private byte FEstrato; private string FSexo; public TPersona(){ FCodigo = 0; FApellidos = "" "";; FNombres = "" "";; FEdad = 0; FEstrato = 0; FSexo = "" "";; } public int Codigo{ set{{ set FCodigo = value value;; } get{{ get return FCodigo; } }
public byte Edad{ set{{ set FEdad = value value;; } get{{ get return FEdad; } } public byte Estrato{ set{{ set FEstrato = value value;; } get{{ get return FEstrato; } } public string Sexo{ set{{ set FSexo = value value;; } get{{ get return FSexo; } } }
public string Apellidos{ set{{ set FApellidos = value value;; } get{{ get return FApellidos; } } public string Nombres{ set{{ set FNombres = value value;; } get{{ get return FNombres; } }
Lic. Luis Roberto Olascoaga Surmay
c) Repita el paso (a) pero esta vez en la ventana desplegada asigne TEscritura como nombre de la clase y haga click en el botón Nuevo como se indica en la siguiente imagen:
Para implementar esta clase borre el nombre de espacio (namespace) dentro del código y asegúrese que el código para la clase TEscritura sea como sigue: using System; using System.IO; public abstract class TEscritura{
public bool Abrir(bool Abrir( bool Agregar){ try{{ try Cerrar(); if(Agregar) if (Agregar) FEscritor=File.AppendT FEscritor=File.AppendText(FNombre); ext(FNombre);
private string FNombre; protected StreamWriter FEscritor; public TEscritura(){ FNombre=null FNombre=null;; FEscritor=null FEscritor=null;; } public string Nombre{ set{{ set FNombre=value FNombre=value;; } get{{ get return FNombre; } } public void GuardarLin(string GuardarLin(string Linea){ FEscritor.WriteLine(Linea); }
else FEscritor=File.CreateT FEscritor=File.CreateText(FNombre); ext(FNombre); return true true;; } catch{{ catch return false false;; } } public void Cerrar(){ if(FEscritor!= if (FEscritor!=null null){ ){ FEscritor.Flush(); FEscritor.Close(); FEscritor=null FEscritor=null;; } } }
public abstract bool GuardarObj(object GuardarObj(object Obj);
Lic. Luis Roberto Olascoaga Surmay
e) Repitiendo el paso (a) cree la clase TLectura y haga click en el botón Nuevo como se indica en la siguiente imagen:
Como en los casos anteriores borre namespace dentro del código y asegúrese que la implementación de la clase TLectura quede así: using System; using System.IO;
public string LeerLin(){ return FLector.ReadLine(); }
public abstract class TLectura{ private string FNombre; protected StreamReader StreamReader FLector; public TLectura(){ FNombre="" FNombre="";; FLector=null FLector=null;; } public string Nombre{ set{{ set FNombre=value FNombre=value;; } get{{ get return FNombre; } } public bool EsFinal(){ return FLector.EndOfStream; }
public bool Abrir(){ try{{ try Cerrar(); FLector=File.OpenText(FNombre); return true true;; } catch{{ catch return false false;; } } public abstract bool LeerObj(object LeerObj(object Obj); public void Cerrar(){ if(FLector!= if (FLector!=null null){ ){ FLector.Close(); FLector=null FLector=null;; } } }
Lic. Luis Roberto Olascoaga Surmay
f) Nuevamente con el paso (a) creamos una nueva clase vacía pero esta vez con el nombre TEscPersona y haga click en el botón Nuevo como se aprecia seguidamente:
Igualmente borre el nombre de espacio dentro del código y asegúrese que la codificación para la clase TEscPersona quede de esta forma: using System; public class TEscPersona : TEscritura{ public TEscPersona() : base base(){ (){ } public override bool GuardarObj(object GuardarObj(object Obj){ TPersona Per; if(Obj if (Obj is TPersona){ Per=Obj as TPersona; GuardarLin(Per.Codigo+ "" ""); ); GuardarLin(Per.Apellidos); GuardarLin(Per.Nombres); GuardarLin(Per.Edad+"" GuardarLin(Per.Edad+ ""); ); GuardarLin(Per.Estrato+"" GuardarLin(Per.Estrato+ ""); ); GuardarLin(Per.Sexo); return true true;; } else return false false;; } }
Lic. Luis Roberto Olascoaga Surmay
g) Fina Finalm lmen ente te sigu siguie iend ndo o el paso paso (a) (a) crea creamo moss la últi última ma clas clase e vací vacía a con con el nomb nombre re TLecPersona y haga click en el botón Nuevo como se muestra a continuación:
Nuev Nuevam amen ente te borre borre el nomb nombre re de espa espaci cio o dent dentro ro del del códi código go y aseg asegúre úrese se que que la implementación para la clase TLecPersona quede de la siguiente manera: using System; public class TLecPersona : TLectura{ public TLecPersona() : base base(){ (){ } public override bool LeerObj(object LeerObj(object Obj){ TPersona Per; if(Obj if (Obj is TPersona){ Per=Obj as TPersona; Per.Codigo=int Per.Codigo= int.Parse(LeerLin()); .Parse(LeerLin()); Per.Apellidos=LeerLin(); Per.Nombres=LeerLin(); Per.Edad=byte Per.Edad= byte.Parse(LeerLin()); .Parse(LeerLin()); Per.Estrato=byte Per.Estrato=byte.Parse(LeerLin()); .Parse(LeerLin()); Per.Sexo=LeerLin(); return true true;; } else return false false;; } }
Lic. Luis Roberto Olascoaga Surmay
7. Diseño de la ventana principal.
Haga doble click en el panel de la solución sobre el archivo MainWindow .cs .cs y en la parte inferior de esta observe dos botones (código fuente y diseñador),
Ahora haga click en el botón diseñador debe ver una imagen previa de la ventana como esta:
Para diseñar la ventana será necesario usar la barra de herramientas y el inspector de propiedades. Para ver estos, nos vamos por la opción Ver del menú principal y hacemos click en el ítem Visual Design, como se indica en la imagen de izquierda. La imagen de la derecha muestra el panel de componentes (barra de herramientas) y debajo de esta el inspector de propiedades con dos fichas en su parte superior: Propiedades y señales (para los eventos). Si aun asi no vemos estos paneles seleccionelos por la opción Ver + Paneles y marcando Barra de herramientas y después propiedades respectivamente.
Lic. Luis Roberto Olascoaga Surmay
Seleccione la ventana y en el inspector de propiedades despliegue el nodo “Window Properties” (haciendo click en la flecha a la izquierda de este). Ubique la propiedad Title (Titulo de la ventana) y escriba delante de esta “Ejemplo archivos de texto”, quedando la ventana como se muestra a continuación.
Ahora en la barra de herramientas asegúrese de estar en el grupo de contenedores y desde este arrastre hasta la ventana un widget llamado VBox que nos divide la ventana en tres (por defecto) paneles horizontales, como se aprecia en la siguiente imagen.
Lic. Luis Roberto Olascoaga Surmay
Construcción del menú principal
Para construir el menú principal de la ventana procedemos así: a) Del grupo componentes de la barra de herramientas arrastre hasta el primer panel del
VBox un Menu Bar (Barra de menú).
b) En la imagen anterior haga click en el texto “haga clic para crear menú” con el objetivo
de definir las opciones del menú. Aquí escriba el texto Archivo y pulse enter según lo muestra la siguiente imagen:
c) Una vez hecho esto el aspecto del menú es como el que se muestra a continuación,
repitiendo el mismo procedimiento haga click en el texto que dice “haga clic para crear opción” para crear los ítems que colgaran de la opción principal archivo.
Lic. Luis Roberto Olascoaga Surmay
d) Haga clic en el texto que dice dice “haga clic para crear opción”, opción”, escriba escriba el texto Abrir y
luego pulse enter como puede ver en la siguiente imagen:
e) Repita Repita este este proceso proceso para añadir añadir las sub opcion opciones es de guarda guardarr y salir, salir, quedan quedando do el menú como se aprecia seguidamente:
f) Haga click en la opción Abrir y en el inspector de propiedades en el nodo llamado
“action properties”, asignele un icono apropiado en la propiedad Stockid:
Lic. Luis Roberto Olascoaga Surmay
g) Haga lo propi propio o para las opcion opciones es Guardar Guardar y Salir Salir de modo que que el menú quede quede como como se indica a continuación:
Widgets para captura de datos
a) Para los controles de captura de datos, primero desde el panel de contenedores de la
barra de herramientas arrastre hasta el panel central del VBox una tabla como se indica en seguida:
Lic. Luis Roberto Olascoaga Surmay
b) Seguidamente ponga por dimensión de la tabla cuatro filas y cinco columnas, para lo
cual en el inspector de propiedades despliegue el nodo “Table properties” de modo que en la propiedad NRows (numero de filas) ponga 4 y en la propiedad NColumns (numero de columnas) asigne 5.
c) Seguidamente en las celdas indicadas de la primera fila de la tabla arrastre tres
Widgets Label desde el grupo componentes de la barra de herramientas. A estas tres etiquetas póngales por título Código, Apellidos y Nombres respectivamente, para lo cual en el inspector de propiedades expanda el nodo Label Properties y escriba el texto adecuado en la propiedad LabelProp.
Lic. Luis Roberto Olascoaga Surmay
d) Seleccione el Label con el titulo apellidos y en el inspector de propiedades expanda el
nodo “Table Child Layout” y ponga la propiedad RightAttach en tres (inicialmente esta en dos, pero se le aumenta en uno para que ocupe dos columnas).
e) Haga la misma operación con el Label de titulo nombres, pero esta vez ponga 5 en la
propiedad RightAttach. RightAttach.
Lic. Luis Roberto Olascoaga Surmay
f) Arrastre de la barra de herramientas del grupo de componentes tres Label hasta las
tres primeras celdas de la tercera fila de la tabla, asignándoles como titulo los textos sexo, edad y estrato respectivamente.
g) A cada cada uno de los los seis seis Label Label
póng póngal ale e 0 en el valo valorr para para la prop propie ieda dad d Xali Xaling ng
seleccionándola desde el nodo de propiedad titulado como “Miscellaneous Alignment Properties” como se observa en la siguiente imagen.
Lic. Luis Roberto Olascoaga Surmay
h) Hasta las dos primeras celdas de la segunda fila de la tabla arrastre dos Entry cuyos
nombres serán E1 y E2. Seleccione el segundo Entry y en el nodo “Table Chile Layout” ponga el valor de 3 en la propiedad RightAttach RightAttach para que ocupe dos celdas..
i) Arrastre otro Entry déle por nombre E3 y asigne el valor de 5 en la propiedad
RightAttach.
Lic. Luis Roberto Olascoaga Surmay
j) Seleccione el primer Entry y en el nodo de propiedades llamado “Common Widget
Prop Proper ertities es”” busq busque ue la prop propie ieda dad d Widt WidthR hReq eque uest st (anc (ancho ho del del cont contro rol) l) marq marque ue el checkbox y ponga el valor de 100.
k) Arrastre un ComboBox hasta la primera celda de cuarta fila de la tabla, seleccione la
propiedad Ítems, haga clic en el botón de tres puntos que esta a la derecha de esta e ingrese los valores de Masculino y Femenino uno debajo del otro y pulse el boton aceptar. A este control póngale por nombre Cb1.
Lic. Luis Roberto Olascoaga Surmay
l) Arrastre otro dos Entry hasta la segunda y tercera celda de la cuarta fila, asignándoles
por nombre E4 y E5 respectivamente. Además póngales a ambos el valor de 50 en la propiedad WidthRequest.
m) Arrastre un botón hasta la cuarta celda de la cuarta fila de la tabla. Expanda el nodo
de propiedades “Button “Button Properties” y ponga los valores valores indicados a las propiedades propiedades según la siguiente imagen:
Lic. Luis Roberto Olascoaga Surmay
n) Ponga otro botón botón hasta la quinta celda celda de la cuarta fila de la tabla. En el nodo nodo “Button
Poroperties” ponga los valores indicados a las propiedades según la imagen siguiente:
o) Haga click derecho sobre el ultimo panel del VBox para agregar un nuevo panel
tomando para ello la opción “Insert Alter”
Lic. Luis Roberto Olascoaga Surmay
p) Ahora arrastre una barra de progreso (ProgressBar) hasta el penúltimo panel del VBox
que tendrá por nombre prg. Seguidamente expanda el nodo de propiedades “Common Widget Widget Proper Propertie ties” s” desmar desmarcam camos os la casill casilla a de la propie propiedad dad Visib Visible, le, para para que en ejecución el componente no sea vea.
q) Finalmente en el último panel arrastre un TreeView que tendrá como nombre Trv,
quedando el diseño final de la ventana según la siguiente imagen.
Lic. Luis Roberto Olascoaga Surmay
8. Implementación de métodos de la ventana
En la ventana implementaremos los siguientes métodos que se describen brevemente a continuación:
CrearColumnas: Con este método definimos las columnas y títulos del TreeView,
asegurándonos que sean redimensionables. Así mismo creamos el modelo con los tipos de cada columna, considerando para ello la funcion typeof indicandole el tipo adecuado para cada caso y usando como objeto de renderizado para cada columna una instancia de la clase CellRenderText, la cual se relaciona con la propiedad “text” con cada columna del modelo.
Agregar : Añade al modelo del TreeView los datos de las propiedades de un objeto de
la clase TPersona.
Cargar : Recibe un nombre de archivo y lee objetos de la clase TPersona que son
añadidos hasta el TreeView.
Asignar : Método sobrecargado, sobrecargado, en el que la primera sobre carga recibe un objeto de la
clase TPersona y llena el valor de sus propiedades desde los datos ingresados en los contr controle oless (Widg (Widgets ets)) de la ventan ventana. a. La segund segunda a sobre sobre carga carga además además recibe recibe un segundo parámetro la fila (TreeIter) del modelo de datos del TreeView desde la que se toman los valores de las propiedades del objeto.
Guardar : Recibe un nombre de archivo y guarda todos los objetos de la clase TPersona hasta un archivo de texto, que fueron previamente leídos desde un archivo
de texto y/o ingresados en el TreeView.
Limpiar : Recibe Recibe por parámetr parámetro o una cantid cantidad ad variab variable le de Widget Widgetss del tipo Entry Entry
(usando la palabra reservada params ) para limpiar el texto ingresado por el usuario.
Ahora trasládese a la vista de código fuente de la ventana y asegúrese de que el código de la misma quede como se indica a continuacion:
Lic. Luis Roberto Olascoaga Surmay
using System; using Gtk; public partial class MainWindow : Gtk.Window{ private ListStore Mod; public MainWindow () : base base(Gtk.WindowType.Toplevel){ (Gtk.WindowType.Toplevel){ Build(); CrearColumnas(); } private void CrearColumnas(){ int i; string [ ]Titulos={"Codigo" ]Titulos={"Codigo",,"Apellidos" "Apellidos",,"Nombres" "Nombres",,"Sexo" "Sexo",,"Edad" "Edad",,"Estrato" "Estrato"}} ; Mod=new Mod=new ListStore( typeof typeof((int int), ),typeof typeof((string string), ),typeof typeof((string string), ),typeof typeof((string string), ),typeof typeof((byte byte), ),typeof typeof((byte byte)); )); for(i=0 for(i= 0;i
Lic. Luis Roberto Olascoaga Surmay
private void Guardar(string Guardar(string NomArch){ int i; TPersona Per; TreeIter Fila; TEscPersona EP=new EP=new TEscPersona(); EP.Nombre=NomArch; if(EP.Abrir( if (EP.Abrir(false false)){ )){ Per=new Per=new TPersona(); for(i= for (i=0 0;i
9. Implementación de eventos de la ventana
Para implementar los eventos de los botones y de las opciones del menú procedemos así: a) Seleccione el botón Agregar y active la ficha de señales (eventos) del inspector de
propiedades. Luego expanda el nodo “Buttons Signals” y haga doble click en el evento llamado “Clicked”:
Lic. Luis Roberto Olascoaga Surmay
Implemente el evento del botón Agregar con el siguiente código: protected virtual void OnButton1Clicked(object OnButton1Clicked(object sender, System.EventArgs e){ TPersona Per=new Per=new TPersona(); Asignar(Per); Agregar(Per ); Limpiar(E1,E2,E3,E4,E5); }
b) Ahora seleccione el botón Eliminar y en la ficha de señales dentro del nodo “Buttons
Signals” y haga doble click en el evento llamado “Clicked”:
Implemente el evento del botón Eliminar con el siguiente código:
protected virtual void OnButton2Clicked(object OnButton2Clicked(object sender, System.EventArgs e){ TreeIter Fila; if(Trv.Selection.GetSelected( if (Trv.Selection.GetSelected(out Fila)) Mod.Remove(ref Mod.Remove( ref Fila); }
c) Para implementar las opciones de la barra de menú, empiece seleccionando la opción
Abrir, expanda el nodo de señales llamado “Action Signals” y haga doble click en la señal “Activated”
Lic. Luis Roberto Olascoaga Surmay
El código para implementar la opción de menú “Abrir” es el siguiente: protected virtual void OnOpenActionActivated( OnOpenActionActivated(object object sender, System.EventArgs System.EventArgs e){ FileChooserDialog FileChooserDialog Dlg; Dlg=new Dlg=new FileChooserDialog( "Abrir archive personas", personas",this this,FileChooserAction.Open, ,FileChooserAction.Open, Stock.Open,ResponseType.Ok,S Stock.Open,ResponseType.Ok,Stock.Cancel,ResponseT tock.Cancel,ResponseType.Cancel); ype.Cancel); Dlg.Filter=new Dlg.Filter=new FileFilter(); Dlg.Filter.AddPattern("*.txt" Dlg.Filter.AddPattern( "*.txt"); ); if(Dlg.Run()==( if (Dlg.Run()==(int int)ResponseType.Ok) )ResponseType.Ok) Cargar(Dlg.Filename); Dlg.HideAll(); Dlg.Destroy(); }
d) La siguiente opción del menú es Guardar, selecciónela y haga doble click en la señal
“Activated”:
El código para implementar la opción de menú “Guardar” queda así: protected virtual void OnSaveActionActivated( OnSaveActionActivated(object object sender, System.EventArgs e){ FileChooserDialog FileChooserDialog Dlg; Dlg=new Dlg=new FileChooserDialog( "Guardar archivo personas", personas",this this,FileChooserAction.Save, ,FileChooserAction.Save, Stock.Save,ResponseT Stock.Save,ResponseType.Ok,Stock ype.Ok,Stock.Cancel,ResponseT .Cancel,ResponseType.Cancel); ype.Cancel); Dlg.Filter=new Dlg.Filter=new FileFilter(); Dlg.Filter.AddPattern("*.txt" Dlg.Filter.AddPattern( "*.txt"); ); if(Dlg.Run()==( if (Dlg.Run()==(int int)ResponseType.Ok) )ResponseType.Ok) Guardar(Dlg.Filename); Dlg.HideAll(); Dlg.Destroy(); }
Lic. Luis Roberto Olascoaga Surmay
e) Finalmente seleccione la opción Salir y haga doble click en la señal “Activated”
Implemente el evento de la opción del menú Salir de la siguiente manera: protected virtual void OnQuitActionActivated OnQuitActionActivated (object sender, System.EventArgs System.EventArgs e){ this.Dispose(); this .Dispose(); }
La siguiente imagen muestra la ventana en tiempo de ejecución:
Lic. Luis Roberto Olascoaga Surmay
Actividad propuesta.
Como complemento del anterior ejercicio desarrolle las siguientes actividades. 1. Para los parámetros por valor y para los de tipo ref, out y params existentes en C#
explique su funcionamiento y diferencias. 2. Consulte cuales son los miembros de la enumeración ResponseType.
3. Investigue Investigue cual cual es el ensamblado ensamblado y que clases clases de este se utiliza utilizan n para los formatos formatos de de codificación codificación de archivos. 4. Explique para que es el método Run de un cuadro de dialogo. 5. Expli Explique que cual cual es la interp interpret retaci ación ón que tienen tienen los cuatro cuatro último últimoss paráme parámetro tross del
constructor de la clase FileChosserDialog. 6. Modifique Modifique el ejemplo ejemplo anterior anterior insertand insertando o al principio principio una nueva columna columna al TreeVie TreeView w (y consecuentemente al modelo) con el titulo Nº que muestre el número de fila o registro de cada persona. 7. Modifique el código de la ventana del ejemplo presentado para que la operación de
guardado del archivo de texto sea realizada con un hilo, de modo que se muestre en ejecución el progreso de esta operación usando la barra de progreso que dejamos oculta. 8. A la aplicaci aplicación ón anterio anteriorr se le debe debe agregar agregar una nueva nueva opción opción de menú menú al lado de la opción de archivo. Esta nueva opción deberá llamarse Ordenar y contendrá sub opciones para ordenar los datos del modelo del TreeView por código, apellidos y nombres respectivamente. 9. Usando la clase Lectura cree una nueva solución de ventana junto con las clases
nece necesa sari rias as para para leer leer los los dato datoss de los los usua usuari rios os del del sist sistem ema a desd desde e el arch archiv ivo o /etc/passwd. 10. Desarrolle un proyecto de ventana para demostrar el uso de los métodos Copy , Move, Delete y GetLastWirte de la clase File.
Lic. Luis Roberto Olascoaga Surmay