Archivos de Texto en CSharp

Page 1

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

practico en lenguaje C# mediante un proyecto de interfaz grafica de usuario (GUI)

construido con MonoDevelop basado en GTK# 2.0, describiendo ademas 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 de archivos, adicional al uso de 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 MonoDevelop que muestre la 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

Page 2

1. Archivos de Texto

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 nuestros programas pueden ser guardados de manera 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 operaciones propias del sistema operativo (como por ejemplo copiado,

renombrado, asignación de permisos, eliminación etc.) en las que el significado 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

incluye operaciones como la lectura, la escritura o modificación y en todo caso

suponemos que interesa el significado o interpretación del contenido del 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

contenido directamente, al menos desde cualquier editor de texto; incluso 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

Page 3

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. Archivos de Texto 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 directorio desde C# se utiliza el ensamblado System.IO, que contiene clases,

excepciones, estructuras, enumeraciones y demás elementos especializados 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 : Que permite hacer una copia exacta de un archivo dando el nombre del

archivo original y el nombre de la copia (destino).

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 y se le indican el nombre del archivo original y el nuevo nombre o destino

(directorio).

File. Delete : Que borra físicamente un archivo dando el nombre del archivo.

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 : 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

Page 4

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 : 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 Line : 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

todos los cambios o escrituras hechos en el archivo a nivel de memoria 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 Line : 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

Page 5

CurrentEncoding : Propiedad que es un objeto representativo del tipo o formato de

codificación con el que se abrió el archivo.

En dOfStream: 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

secuencia de datos o bytes) relacionada con el flujo de datos del archivo.

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 serán representados por propiedades de la clase TPersona. Se diseñara e

implementara una clase para guardar datos en forma de líneas de caracteres hasta un

archivo de texto, la cual contendrá un método abstracto llamado 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

propiedad (atributo) del objeto TPersona en una línea independiente.

De manera análoga tenemos la clase TLectura, la cual será una clase abstracta

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 de archivo y

por supuesto un método abstracto llamado LeerObj que permitirá recuperar un objeto de

cualquier tipo desde el archivo. Para este efecto se diseña e implementa la 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

Page 6

4. Diseño de clases para archivos de texto y serialización de 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

Page 7

5. Creación de la solución

Para desarrollar el programa de serialización de objetos de la clase TPersona mediante

archivos de texto procedemos de la siguiente manera:

a) Entrar en Monodevelop: Aplicaciones + programación + Monodevelop

b) Crear una nueva solución: Archivo + nuevo + solución.

c) Enseguida se muestra la siguiente ventana, en la que seleccionamos el nodo C# de la

lista de la izquierda, y de la lista del centro escogemos proyecto GTK#2.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 guardar el proyecto. Así mismo es opcional marcar la creacion de un

subdirectorio por separado para la solución. Finalmente pulse el botón adelante.

Lic. Luis Roberto Olascoaga Surmay

Page 8

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 siguiente pantalla muestra el estado inicial de la solución, observándose en la

izquierda el inspector de la 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

Page 9

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 llave de apertura y la ultima llave de cierre. En la implementación del método

estático Main tenemos el uso del ensamblado Gtk, el llamado de métodos del objeto

global implícito Application, además de la creación de una instancia de la clase

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

Page 10

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

Page 11

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{ FCodigo = value; } get{ return FCodigo; } } public string Apellidos{ set{ FApellidos = value; } get{ return FApellidos; } } public string Nombres{ set{ FNombres = value; } get{ return FNombres; } }

public byte Edad{ set{ FEdad = value; } get{ return FEdad; } } public byte Estrato{ set{ FEstrato = value; } get{ return FEstrato; } } public string Sexo{ set{ FSexo = value; } get{ return FSexo; } } }

Lic. Luis Roberto Olascoaga Surmay

Page 12

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:

Lic. Luis Roberto Olascoaga Surmay

using System; using System.IO; public abstract class TEscritura{ private string FNombre; protected StreamWriter FEscritor; public TEscritura(){ FNombre=null; FEscritor=null; } public string Nombre{ set{ FNombre=value; } get{ return FNombre; } } public void GuardarLin(string Linea){ FEscritor.WriteLine(Linea); } public abstract bool GuardarObj(object Obj);

public bool Abrir(bool Agregar){ try{ Cerrar(); if(Agregar) FEscritor=File.AppendText(FNombre); else FEscritor=File.CreateText(FNombre); return true; } catch{ return false; } } public void Cerrar(){ if(FEscritor!=null){ FEscritor.Flush(); FEscritor.Close(); FEscritor=null; } } }

Page 13

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

Lic. Luis Roberto Olascoaga Surmay

using System; using System.IO; public abstract class TLectura{ private string FNombre; protected StreamReader FLector; public TLectura(){ FNombre=»»; FLector=null; } public string Nombre{ set{ FNombre=value; } get{ return FNombre; } } public bool EsFinal(){ return FLector.EndOfStream; }

public string LeerLin(){ return FLector.ReadLine(); } public bool Abrir(){ try{ Cerrar(); FLector=File.OpenText(FNombre); return true; } catch{ return false; } } public abstract bool LeerObj(object Obj); public void Cerrar(){ if(FLector!=null){ FLector.Close(); FLector=null; } } }

Page 14

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(){ } public override bool GuardarObj(object Obj){ TPersona Per; if(Obj is TPersona){ Per=Obj as TPersona; GuardarLin(Per.Codigo+»»); GuardarLin(Per.Apellidos); GuardarLin(Per.Nombres); GuardarLin(Per.Edad+»»); GuardarLin(Per.Estrato+»»); GuardarLin(Per.Sexo); return true; } else return false; } }

Lic. Luis Roberto Olascoaga Surmay

Page 15

g) Finalmente siguiendo el paso (a) creamos la última clase vacía con el nombre

TLecPersona y haga click en el botón Nuevo como se muestra a continuación:

Nuevamente borre el nombre de espacio dentro del código y asegúrese que la

implementación para la clase TLecPersona quede de la siguiente manera:

Lic. Luis Roberto Olascoaga Surmay

using System; public class TLecPersona : TLectura{ public TLecPersona() : base(){ } public override bool LeerObj(object Obj){ TPersona Per; if(Obj is TPersona){ Per=Obj as TPersona; Per.Codigo=int.Parse(LeerLin()); Per.Apellidos=LeerLin(); Per.Nombres=LeerLin(); Per.Edad=byte.Parse(LeerLin()); Per.Estrato=byte.Parse(LeerLin()); Per.Sexo=LeerLin(); return true; } else return false; } }

Page 16

7. Diseño de la ventana principal.

Haga doble click en el panel de la solución sobre el archivo MainWindow.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

Page 17

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

Page 18

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

Page 19

d) Haga clic en el texto que dice “haga clic para crear opción”, escriba el texto Abrir y

luego pulse enter como puede ver en la siguiente imagen:

e) Repita este proceso para añadir las sub opciones de guardar y salir, quedando 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

Page 20

g) Haga lo propio para las opciones Guardar y Salir de modo que el menú quede 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

Page 21

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

Page 22

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.

Lic. Luis Roberto Olascoaga Surmay

Page 23

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 uno de los seis Label póngale 0 en el valor para la propiedad Xaling

seleccionándola desde el nodo de propiedad titulado como “Miscellaneous Alignment

Properties” como se observa en la siguiente imagen.

Lic. Luis Roberto Olascoaga Surmay

Page 24

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

Page 25

j) Seleccione el primer Entry y en el nodo de propiedades llamado “Common Widget

Properties” busque la propiedad WidthRequest (ancho del control) marque 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

Page 26

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 Properties” y ponga los valores indicados a las propiedades

según la siguiente imagen:

Lic. Luis Roberto Olascoaga Surmay

Page 27

n) Ponga otro botón hasta la quinta celda de la cuarta fila de la tabla. En el 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

Page 28

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 Properties” desmarcamos la casilla de la propiedad Visible, 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

Page 29

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, 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

controles (Widgets) de la ventana. La segunda sobre carga además 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 por parámetro una cantidad variable de Widgets del tipo 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

Page 30

using System; using Gtk; public partial class MainWindow : Gtk.Window{ private ListStore Mod; public MainWindow () : base(Gtk.WindowType.Toplevel){ Build(); CrearColumnas(); } private void CrearColumnas(){ int i; string [ ]Titulos={«Codigo»,»Apellidos»,»Nombres»,»Sexo»,»Edad»,»Estrato»} ; Mod=new ListStore(typeof(int),typeof(string),typeof(string),typeof(string),typeof(byte),typeof(byte)); for(i=0;i

Lic. Luis Roberto Olascoaga Surmay

Page 31

private void Guardar(string NomArch){ int i; TPersona Per; TreeIter Fila; TEscPersona EP=new TEscPersona(); EP.Nombre=NomArch; if(EP.Abrir(false)){ Per=new TPersona(); for(i=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

Page 32

Implemente el evento del botón Agregar con el siguiente código:

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:

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

protected virtual void OnButton1Clicked(object sender, System.EventArgs e){ TPersona Per=new TPersona(); Asignar(Per); Agregar(Per ); Limpiar(E1,E2,E3,E4,E5); }

protected virtual void OnButton2Clicked(object sender, System.EventArgs e){ TreeIter Fila; if(Trv.Selection.GetSelected(out Fila)) Mod.Remove(ref Fila); }

Page 33

El código para implementar la opción de menú “Abrir” es el siguiente:

protected virtual void OnOpenActionActivated(object sender, System.EventArgs e){ FileChooserDialog Dlg; Dlg=new FileChooserDialog(«Abrir archive personas»,this,FileChooserAction.Open, Stock.Open,ResponseType.Ok,Stock.Cancel,ResponseType.Cancel); Dlg.Filter=new FileFilter(); Dlg.Filter.AddPattern(«*.txt»); if(Dlg.Run()==(int)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(object sender, System.EventArgs e){ FileChooserDialog Dlg; Dlg=new FileChooserDialog(«Guardar archivo personas»,this,FileChooserAction.Save, Stock.Save,ResponseType.Ok,Stock.Cancel,ResponseType.Cancel); Dlg.Filter=new FileFilter(); Dlg.Filter.AddPattern(«*.txt»); if(Dlg.Run()==(int)ResponseType.Ok) Guardar(Dlg.Filename); Dlg.HideAll(); Dlg.Destroy(); }

Lic. Luis Roberto Olascoaga Surmay

Page 34

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 (object sender, System.EventArgs e){ this.Dispose(); }

La siguiente imagen muestra la ventana en tiempo de ejecución:

Lic. Luis Roberto Olascoaga Surmay

Page 35

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 cual es el ensamblado y que clases de este se utilizan para los formatos de

codificación de archivos.

4. Explique para que es el método Run de un cuadro de dialogo.

5. Explique cual es la interpretación que tienen los cuatro últimos parámetros del

constructor de la clase FileChosserDialog.

6. Modifique el ejemplo anterior insertando al principio una nueva columna al TreeView (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ón anterior se le debe agregar una nueva opción de 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

necesarias para leer los datos de los usuarios del sistema desde el archivo

/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

Publicaciones Similares