DNM+ Online
dotnetmania 2.0
Configuración (Settings) El configurador que lo configure...
Cualquier aplicación que se precie debe tener en cuenta las preferencias de los usuarios, pero incluso si la aplicación no es “amigable” con el usuario que la utiliza, usará con total seguridad datos de configuración. En este artículo veremos cómo podemos gestionar esos datos de configuración utilizando las facilidades que nos proporciona Visual Studio 2005.

Configuración de aplicaciones en Visual Studio 2005 En Visual Studio 2005 se introdujo en las propiedades del proyecto un nuevo apartado, que es precisamente sobre lo que trata este artículo: la ficha "Settings" ("Configuración" en la versión en castellano). Por medio de esa ficha podemos definir los datos de configuración que usará nuestra aplicación. Esos datos de configuración pueden tener dos niveles, según queramos que sean a nivel de la aplicación (válida para todos los usuarios) o que esos datos sean particulares a cada usuario. En el primer caso, los datos serán de solo lectura; es decir, no podremos modificarlos en tiempo de ejecución, sino que solo podremos leer los valores asignados. Por otra parte, los datos de configuración a nivel de usuario son valores de lectura/escritura, y por tanto los podremos modificar en tiempo de ejecución, que es lo deseable, ya que así podremos guardar las preferencias de cada usuario, como por ejemplo el tamaño y posición de la ventana, algunos de los valores con los que normalmente trabajará, etc. La razón de que los valores de configuración a nivel de aplicación sean de solo lectura es para que el usuario no pueda cambiar un valor que en realidad es "global" al resto de usuarios; por tanto, si necesitamos valores "personalizables" por cada usuario, usaremos el ámbito de usuario. Pero si necesitamos valores modificables a nivel de toda la aplicación, tendremos que hacerlo manualmente; Visual Studio no nos proporciona ninguna forma automatizada de que los valores de configuración con ámbito de aplicación se puedan modificar en tiempo de ejecución, y por tanto tendremos que usar nuestra propia forma de acceder y modificar esos valores, ya sea escribiendo directamente en el propio fichero de configuración de la aplicación o, mejor aún, creando nuestro propio fichero de configuración. En el código que acompaña a este artículo incluyo una clase (ConfigXml) que nos puede servir para realizar esas configuraciones personalizadas. Tipos de datos de los valores de configuración Los tipos de datos que podemos usar en la configuración son muy variados, e incluyen los tipos "normales" de .NET, y según estemos usando un lenguaje de programación u otro, esos tipos de datos se mostrarán según la definición de los mismos en el lenguaje; por ejemplo, en C# se nos mostrará string, bool o int, mientras que en Visual Basic será String, Boolean o Integer. También se incluyen tipos más complejos, como StringCollection o Font, aunque en realidad podemos usar prácticamente cualquier tipo de datos definido en .NET Framework e incluso en nuestro propio proyecto; en un momento veremos cómo. Añadir valores de configuración a nuestras aplicaciones Veamos cómo podemos añadir valores de configuración (y usarlos posteriormente) en nuestras aplicaciones.
Crear valores de configuración Para crear valores que usaremos para almacenar datos de configuración debemos pulsar en las propiedades del proyecto ("My Project" en Visual Basic, "Properties" en C#) y seleccionar la ficha "Settings". Se nos mostrará algo como lo que aparece en la figura 1. Viendo la figura 1 y dejándonos llevar por la intuición, podemos deducir que en "Nombre" pondremos cómo queremos que se llame ese valor de configuración, en "Tipo" el tipo de datos que tendrá (inicialmente siempre se muestra string), en "Ámbito" pondremos si queremos que sea una valor a nivel de "Usuario" o de "Aplicación" y en "Valor" el valor inicial que queremos que tenga. Ese valor debe ser adecuado para el tipo de datos; por ejemplo, en la figura 2 tenemos varios valores de configuración añadidos, entre los que hay uno de tipo bool, y en ese caso, las opciones que nos muestra son True y False (con la primera letra en mayúsculas, ya que no son tipos de C# sino valores que se guardarán como cadenas y después se convertirán adecuadamente). Si necesitamos datos más complejos, por ejemplo una colección de datos, también podemos indicarlo. Tal como vemos en la figura 2, el valor de configuración "Ficheros" será del tipo StringCollection. Y en este caso, si queremos asignarle un valor inicial, veremos que el propio Visual Studio nos muestra una ventana en la que podemos indicar cada uno de los elementos que la colección tendrá (ver la figura 3). Y si lo que necesitamos es algunos de los tipos de da­tos que no se han mos­trado en la lista desplegable con los tipos a elegir, podemos seleccionar la última opción ("Examinar"); eso hará que se muestre una ventana con los tipos de datos que podemos seleccionar, tal como vemos en la figura 4. Y si el tipo que queremos usar no está, lo podemos indicar, como es el caso de la clase Colegas que tenemos en nuestro proyecto. En este último caso, debemos tener en cuenta que al usar ese tipo que tenemos definido en nuestro proyecto, se agrega una referencia a nuestra aplicación; la solución es eliminar esa referencia y asunto arreglado. Pero no vamos a complicarnos demasiado, ya que en ese caso no veremos las cosas importantes de todo esto de la configuración, que es lo que en realidad importa. Así que veamos ahora cómo usar los datos de configuración. Acceder a los datos de configuración Una vez que hemos definido los valores que queremos usar en nuestra aplicación, ahora toca poder utilizarlos. En nuestro ejemplo vamos a usar los valores de configuración que podemos ver en la figura 2. Lo bueno del sistema de configuración generado por Visual Studio 2005 es que esos valores los usaremos como propiedades de una clase "especial" que se añade a nuestro proyecto. Esa clase se llama Settings y en C# está definida en un espacio de nombres llamado Properties, que su vez está definido dentro del espacio de nombres de nuestra aplicación. Y debido a que es una clase donde están las propiedades de los valores de configuración, podríamos pensar que tendríamos que crear una instancia de esa clase para poder accederlas; pero esto no es necesario, ya que el propio compilador de C# define una propiedad estática (compartida) en esa misma clase que nos permite acceder a esas propiedades que hacen referencia a los valores de configuración. Esa propiedad se llama Default e internamente accede a un campo que crea una instancia de la propia clase. Sabiendo esto, la forma de acceder a esos valores será el siguiente:

this.Left =
Properties.Settings.Default.Left;

Al definirse como propiedades de una clase, la forma de usarlas es bastante intuitiva. Y como podemos comprobar, los tipos de datos de esas propiedades son los mismos que hemos definido en la configuración; en este ejemplo el tipo "interno" de la propiedad Left es int, por lo que no tenemos que hacer ningún tipo de conversión a la hora de asignar el valor. Si los valores a los que hacen referencia esas propiedades han cambiado y queremos "persistirlas", lo primero que tenemos que hacer es asignar el valor, por ejemplo:

Properties.Settings.Default.Left =
this.Left; Y para que esos datos se guarden tenemos que llamar al método Save:

Properties.Settings.Default.Save(); Es importante llamar al método Save para asegurarnos de que los datos se guardan. Y debemos llamarlo siempre que creamos conveniente, aunque lo recomendable es hacer esa llamada cuando el formulario se vaya a cerrar, es decir, en el evento FormClosing. Sin querer confundir las cosas, me gustaría hacer una aclaración para los lectores que prefieren usar VB como lenguaje de programación, y es que en él de forma predeterminada no es necesario llamar explícitamente al método Save, ya que el compilador se encarga de añadir la llamada a ese método cuando el formulario se cierra. Al menos si así lo hemos indicado en las propiedades del proyecto, marcando la opción "Guardar My.Settings" al cerrar. Precisamente porque My.Settings es otra funcionalidad que ofrece Visual Basic para gestionar todo el tema de las configuraciones, y en realidad consiste en la definición de una propiedad llamada Settings que está definida en un módulo (y por tanto no es necesario indicar dónde está definida), y además este módulo está definido en el espacio de nombres My, por tanto, la forma de usar los valores de configuración en Visual Basic es la siguiente:

Me.Left = My.Settings.Left

En el fondo, esa propiedad Settings lo que hace es utilizar la propiedad "auto-instanciable" Default. En C# podemos acceder fácilmente a esa propiedad Default sin necesidad de escribir tanto, definiendo una variable en el formulario que simplemente haga referencia a esa propiedad "predeterminada":

Properties.Settings misProp =
Properties.Settings.Default;

De esta forma podremos acceder más fácilmente a las propiedades de configuración:

misProp.Top = this.Top; Recibir notificaciones cuando cambien los valores de configuración Otra funcionalidad que Visual Studio 2005 pone a nuestra disposición es la de saber cuándo se va a asignar un valor a una propiedad de configuración o cuándo se va a guardar o cuándo se han cargado los valores. Cuando queremos acceder a esos eventos de configuración, Visual Studio crea una clase parcial con instrucciones para usar dos de los cuatro eventos disponibles: SettingChanging y SettingsSaving.
El primero de los eventos anteriores se produce antes de que cambie uno de los valores de configuración, permitiendo cancelar la asignación. El segundo se produce antes de que se guarden los valores, y también podemos cancelarlo, aunque en este caso no tenemos acceso a los datos que se están guardando salvo que accedamos a las propiedades de la propia clase; sin embargo, con el evento que nos informa de los cambios de las propiedades, en la variable del segundo parámetro se pasa información sobre la propiedad afectada, el nuevo valor a asignar, etc., lo que veremos a continuación con más detalle. Los otros dos eventos son PropertyChanged y SettingsLoaded. En el primero se nos avisa cuando una propiedad ha cambiado, y la única información pasada en el segundo parámetro es el nombre de la propiedad que ha cambiado. El segundo evento se dispara después de la carga de los valores de configuración. La forma de acceder a ese fichero de código es desde la ficha "Configuración" de las propiedades del proyecto y pulsando el botón "Ver código" que está en la parte superior de esa ficha, tal como podemos comprobar en la figura 1. Al pulsar ese botón, se abrirá un fichero con parte del código que normalmente usaremos; en particular, hay definidos dos de los métodos que interceptarán los eventos SettingChanging y SettingsSaving, y en el constructor de la clase están comentadas las instrucciones que ligarán esos métodos con los eventos. Si queremos interceptar los otros dos eventos, tendremos que escribir sus "manejadores" por nuestra cuenta; como ya vimos en el número 31 de dotNetManía, el propio editor de C# nos ayuda a la creación de los mismos. Si nos decidimos a interceptar el evento SettingChanging para detectar los cambios antes de que se asignen a las propiedades, debemos tener en cuenta que los valores pasados en la variable del segundo parámetro no son tipos "explícitos"; es decir, si el cambio se produce en el valor Left, que como vimos es de tipo entero, en este evento se recibe dicho valor como object, porque ese mismo evento sirve para todos los valores de configuración, y como hemos comprobado podemos usar prácticamente cualquier tipo de datos. Por tanto, si queremos detectar el cambio en esa propiedad, tendremos que hacer la conversión correspondiente, tal como vemos en el siguiente código: Como vemos, el nombre del valor de configuración lo averiguamos por medio de SettingName, y el nuevo valor que se va a asignar está en NewValue. Y si no queremos que ese nuevo valor se asigne, simplemente asignamos un valor verdadero a la propiedad Cancel. Trabajar con colecciones
genéricas personalizadas Al definir los valores de configuración no podemos utilizar directamente tipos genéricos, pero nada impide que podamos definir un tipo de datos propio que esté derivado de un tipo genérico y lo utilicemos. Por ejemplo, en nuestro proyecto podemos tener creado un tipo de datos llamado Colega, y podemos querer almacenar instancias de esa clase en una colección genérica de tipo List<Colega>. Debido a que Visual Studio no nos permite usar ese tipo para un valor de configuración, lo que podemos hacer es definir nuestra clase/colección Colegas de esta forma:

public class Colegas : List<Colega> {} Esto simplemente hará que usemos la clase Colegas como una colección genérica, pudiendo añadir valores de esta forma:

Colegas cols = new Colegas(); Colega c = new Colega("Guille"); cols.Add(c); cols.Add(new Colega("Pepe")); Y si hemos definido en la configuración una propiedad que sea del tipo Colegas que hemos definido en nuestro proyecto, tal como vimos en la figura 4, podemos asignar valores de este tipo a la configuración de esta forma: Properties.Settings.Default.Colegas =
cols; Y por supuesto, podemos acceder a ese valor de la forma habitual, además sin necesidad de hacer ningún tipo de conversión, ya que en las propiedades de la clase Settings siempre se almacenan los datos usando el tipo que hemos indicado. En el siguiente código obtenemos los valores de los "colegas" que tengamos en el fichero de configuración y los asignamos a un control ListBox:

Colegas cols = Properties.Settings.Default.Colegas; this.listBox1.Items.AddRange( cols.ToArray()); Enlace de propiedades con valores de configuración Algo muy habitual en el manejo de los valores de configuración es hacer binding de ciertas propiedades de los controles o del formulario a valores almacenados en la configuración de la aplicación. Tan habitual es, que es prácticamente casi todo lo que la documentación de Visual Studio muestra como ejemplos, y "casi" lo único que se podía hacer en las versiones anteriores de Visual Studio, aunque a diferencia de éstas, en Visual Studio 2005 esos valores pueden tener un ámbito de usuario en lugar de ser solo a nivel de aplicación, con lo cual se facilita su uso. La forma de ligar cualquier propiedad de cualquier control (o del formulario) a un valor de configuración es mediante la ventana de propiedades, en particular de la propiedad "ApplicationSettings", que en el caso del formulario, mostrará los valores que vemos en la figura 5. Como vemos en la figura 5, para el formulario hay dos propiedades preparadas para recibir el valor. Esas propiedades dependerán del control que estemos usando, pero si la propiedad que queremos "persistir" no está en esa lista de propiedades, podemos pulsar en "PropertyBinding" y desde el cuadro de diálogo que se nos mostrará podremos seleccionar la propiedad que queremos ligar con un valor de configuración. Si ya tenemos un valor de configuración del tipo adecuado, podemos usar esa propiedad o bien crear una nueva; en ese caso, como vemos en la figura 6, podemos crearla directamente desde ese mismo cuadro de diálogo. Al crearla desde este cuadro de diálogo, podemos indicar el ámbito que queremos que tenga ese valor de configuración además de asignar los valores que queremos que tenga. Y tal como vemos en la figura 7, en la que asignamos el valor de la propiedad ClientSize, se mostrará el valor que actualmente tenga la propiedad que queremos usar. Una vez que tenemos las propiedades enlazadas a valores de configuración, en la ventana de propiedades se nos mostrarán todas las que lo estén, tal como podemos comprobar en la figura 8. Y en cada una de esas propiedades enlazadas tendremos un icono que nos indicará esa situación "de enlace", además de indicársenos cuál es el valor de la configuración con el que la propiedad está enlazada, tal como vemos en la figura 9. Ni que decir tiene que es el propio compilador el que se encarga de implementar todos estos "enlaces", de forma que nosotros no tengamos que escribir código extra para que se hagan efectivos. Lo único que tendremos que escribir (si estamos usando C#) es la llamada al método Save de la clase Settings a la hora de guardar los datos de configuración, y como ya comenté antes, el mejor sitio en el que podemos llamar a ese método es en el evento FormClosing, para que se guarden los valores de configuración cuando el formulario se esté cerrando y no perdamos nada. Como truco, decir que hay ciertas propiedades que tienen un comportamiento no esperado, como es el caso de la propiedad Checked de los controles RadioButton, ya que el comportamiento esperado de ese tipo de controles es que al seleccionar un control de un grupo, el resto se deseleccione, pero al estar la propiedad Checked enlazada, esa "magia" se pierde, y tendremos que ser nosotros mismos los que tengamos que asignar los valores adecuados a cada una de las opciones que estén en un mismo rango. Además de que para ese tipo de controles, al tener esa propiedad enlazada, el comportamiento en tiempo de ejecución no es... nada deseable. Por tanto, mi recomendación es la de no enlazar automáticamente las propiedades Checked de los controles RadioButton y si lo necesitamos, hacerlo manualmente, aunque, como es natural, usando los valores de configuración. Configuraciones totalmente personalizadas Esto de que el propio Visual Studio proporcione una forma automatizada de almacenar valores de configuración está muy bien. El problema principal es que los valores de configuración a nivel de aplicación son de solo lectura, es decir, no podemos almacenar nuevos valores. Por un lado es lógico ese comportamiento, ya que así un usuario no alterará los valores que todos los usuarios van a usar. Pero hay casos en los que nos puede interesar que sí se puedan modificar ciertos valores, por ejemplo, la localización de una base de datos o de un fichero con cierta información que todos los usuarios de la aplicación usarán. En estos casos, podemos actuar de dos formas. Una es creando nuestro propio sistema de almacenar los datos de configuración; por ejemplo, yo suelo usar una clase llamada ConfigXml que utilizo en la mayoría de los casos en los que necesito que los valores de configuración estén compartidos con todos los usuarios (incluso la uso para que cada usuario tenga sus propios datos, pero eso más que nada es por costumbre de usar las cosas que me funcionan y sobre las que tengo más control). La otra forma de modificar valores del propio fichero de configuración es accediendo directamente a dicho fichero, que suele tener el nombre de la aplicación con la extensión .config y que suele estar en el directorio del ejecutable (los cambios realizados en Windows Vista serán en el directorio roaming, pero para nuestro uso eso no afecta). Como el fichero de configuración tiene formato XML, lo más fácil es usar una variable de tipo XmlDocument y sabiendo cómo se almacenan los datos, nos resultará fácil escribir un método que se encargue de hacer esas modificaciones por nosotros. En realidad, el acceso manual solo lo tenemos que hacer para almacenar los valores, ya que la lectura de esos valores es automática y se realiza al iniciarse la aplicación. Veamos cómo podemos modificar esos valores. Lo primero es definir una variable a nivel del formulario, ya que la usaremos tanto en el evento FormClosing como desde un método que será el que se encargue de guardar los datos. Después definimos el método que se encarga de almacenar los datos en el fichero de configuración y finalmente, en el evento de cierre del formulario asignamos esos valores. Si no queremos tener que escribir código extra, esos valores los debemos tener "ligados" a las propiedades del formulario o de los controles que nos interese que reflejen los valores de la configuración. Una observación: si queremos "persistir" la posición del formulario, la propiedad StartPosition de éste debe tener el valor Manual. En el listado 1 tenemos todo el código necesario para hacer esto que acabamos de comentar. Para no alargar demasiado el artículo, en los comentarios del código se explica el truco para poder acceder correctamente a los valores de configuración. Conclusiones En este artículo hemos visto cómo trabajar con los valores de configuración en nuestras aplicaciones creadas con Visual C# 2005, en las que aprovechamos la funcionalidad que nos da el entorno de desarrollo para automatizar todo el trabajo de asignación y recuperación de los valores de configuración. Y como no es plan de olvidarse de los usuarios que utilizan Visual Basic, en el ZIP con el código he incluido también proyectos creados con Visual Basic 2005 en los que se muestra cómo hacer todo lo comentado en el artículo, además de extras que por falta de espacio no he podido explicar, como es la posibilidad de usar la clase ConfigXml o cómo mostrar y modificar los valores de configuración al estilo de la ventana de propiedades del propio Visual Studio 2005.

blog comments powered by Disqus
autor
referencias