Esto que te explico aquí es como una especie de agregado aclaratorio que inicialmente iba a
publicar dentro del artículo sobre la utilidad
gsBuscarTexto (Buscar en ficheros v2.0).
Pero he decidido publicarlo aparte para que resulte más fácil de encontrar que si está dentro de
otro artículo, que después pasa lo que pasa, que como está dentro de algo que a lo mejor no te
interesa, pues no lo lees y no te enteras.
Por supuesto, si ya sabes de qué va todo esto de XAML y XML, puedes irte ahora mismo a ver otras
cosas... Si te quedas, pues... espero que esta explicación te sirva.
Si estás leyendo esto es o porque te interesa saber cómo se definen los controles WPF por
medio de XAML o porque estás aburrido, incluso también porque no te hayas leído lo que comenté
más arriba...
En cualquier caso, lo que te voy a explicar es un poco del "porqué" se definen como se
definen las cosas en XAML y aunque no entre en detalles profundos, al menos te sirva para tener
una idea de porqué se usa el código que se usa...
Antes de nada debes saber que XAML (o mejor dicho XML que es
el "lenguaje" usado para definir los controles WPF por medio de XAML) es un lenguaje que
diferencia mayúsculas de las minúsculas, al menos en el nombre de los elementos y de los
atributos.
¿No sabes lo que es un elemento y un atributo? Mal empezamos, je, je... bueno, vale, te lo
explico.
Elementos y atributos
Todo fichero de XML (recuerda que XAML está basado en XML, sí,
ya se que te lo he dicho, pero...) está formado por un elemento principal que a su vez
contiene otros elementos "hijos". Y cada uno de esos elementos puede tener atributos.
Para entenderlo un poco mejor veamos parte del código del control
OpcionesBuscar.
<UserControl x:Class="OpcionesBuscar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="600" Height="230">
<UserControl.Resources>
<!-- Este estilo se aplicará a todos los CheckBox del control de usuario -->
<Style TargetType="{x:Type CheckBox}">
<Setter Property="Margin" Value="8,4,0,0"/>
</Style>
</UserControl.Resources>
<StackPanel Name="StackMain" VerticalAlignment="Top">
</StackPanel>
</UserControl>
El UserControl que hay al principio es el elemento principal.
Los elementos pueden tener atributos.
Por ejemplos, el elemento UserControl tiene varios atributos como Width, Height,
etc., (los que están en color rojo).
Los elementos a su vez pueden tener otros elementos.
En este caso, UserControl.Resouces y StackPanel son dos elementos que están
"anidados" en el elemento principal. Y si te fijas, el elemento UserControl.Resources a
su vez tiene otro elemento: Style, que a su vez tiene anidado otro elemento: Setter.
Los elementos pueden definirse usando el formato: <Elemento>Contenido</Elemento>, es
decir, el contenido de un elemento se indica con el nombre del elemento, después se indican las
cosas que contiene y se finaliza usando el formato de fin de elemento, que siempre tiene el
formato </Nombre_del_elemento>.
Los elementos también pueden tener el formato <Elemento [atributos] />.
En este caso, no se usa el cierre del elemento como lo hemos visto antes. Y esto es útil si un
elemento no tienen un "contenido" específico.
Ese contenido puede ser algo que contiene (elemental querido
Guille) o bien porque contenga otros elementos, como es el caso de la forma que te mostré
antes.
Pero también puede ser que no tenga un contenido, salvo por lo indicado en las propiedades (o
atributos) del elemento. Si ese es el caso, se puede usar en la forma "abreviada". Ese es el
caso del elemento Setter del ejemplo anterior.
Por supuesto, esos atributos son opcionales, por tanto, si no tiene atributos, es muy posible
que el elemento tenga un contenido; aunque no siempre es así, por ejemplo, si quieres indicar un
separador en un menú, simplemente usarás <Separator /> sin más y el WPF sabrá que lo que
defines es un separador sin atributos ni contenido.
Si un elemento tiene atributos, estos se indican en la definición del inicio del elemento (si
es un elemento con contenido), por ejemplo, el elemento Style tiene un elemento llamado
TargeType, y ese atributo se define después del nombre del elemento, si hay más atributos
en el mismo elemento, estos se separan del anterior en al menos un espacio. Cuando ya hayamos
definido todos los atributos, cerramos el inicio del elemento con el carácter >.
Si el elemento no tiene contenido (ni tampoco contiene otros elementos), los atributos se
indican antes de los caracteres de cierre, que en el caso de los atributos sin contenido se
indica con los caracteres />, el ejemplo lo puedes ver en el elemento Setter.
Los atributos siempre usan el mismo formato, es decir, nombre del atributo, signo igual y
entre comillas dobles el valor de ese atributo. Por ejemplo, el atributo Property del
elemento Setter tiene el valor Margin.
El hecho de que el código esté coloreado nos permite distinguir mejor cada una de las "cosas"
que definimos, pero claro, lo de que esté coloreado es solo para que resulte más fácil la
lectura del código, pasa lo mismo con el código de nuestro lenguaje, y en realidad el XML no
define ninguna norma de coloración, eso solo es cosa de a quién se le haya ocurrido colorear el
código XML, pero en el caso de Internet Explorer y Visual Studio, las normas que se siguen son:
- Los caracteres de apertura y cierre de los elementos se colorean en azul.
- Los nombres de los elementos se colorean en rojo oscuro (FireBrick creo que se llama el
color).
- Los atributos se colorean en rojo.
- Los valores de los atributos se colorean en azul.
- Los comentarios se colorean en verde.
Sigamos con la explicación del formato XAML.
Lo dicho anteriormente sería general para el formato XML y como sabes, XAML que es el
lenguaje de marcado usado para definir el contenido de los controles (y otras cosas) de WPF.
XML no es "estricto" con los elementos y atributos que usemos, salvo para los casos de
nomenclatura, por ejemplo hay ciertos caracteres que no se pueden usar directamente en el código
XML, ni como parte de un nombre de un elemento o de un atributo, por ejemplo, los nombres no
deben contener espacios. Y tampoco podemos usar el signo &, ya que ese signo se usa para
definir otros caracteres, si en un fichero XML queremos incluir el signo ampersand (&)
debemos hacerlo en la forma de &. Esto es aplicable a cualquier cosa que escribamos
para usarlo como XML, por ejemplo en la documentación XML de nuestro código... pero ese es otro
tema.
Lo que pasa es que WPF define sus propios controles y demás elementos y atributos que se
pueden usar en el código XAML de nuestra aplicación. Y si no usamos los elementos y atributos
adecuados, el propio IDE de Visual Studio los marcará como no válidos.
Elementos = controles, atributos = propiedades (o casi)
En cuanto a los atributos XAML usados con los elementos, debes pensar en ellos como si fueran
propiedades de un control, en esto de XAML podemos decir (sin que nadie nos de la bronca) que un
atributo XAML es el equivalente de una propiedad de ese control que está definiendo el elemento.
Dicho esto (y por lógica deducción), también podríamos afirmar que un elemento XAML es el
equivalente de un control.
No es que siempre sea así, pero si te quedas con esta idea, pues... te resultará más fácil saber
qué es lo que estás haciendo... sí, ya sé, después vendrán los que saben más que nosotros
diciendo que eso no siempre es así, pero... tú, ni caso, tu a lo tuyo que... si el otro se
quiere complicar la vida con "tecnicismos" que se la complique... je, je, je.
Y para demostrar que esto que te acabo de decir es cierto, como muestra, un botón, (nunca
mejor dicho), por ejemplo, en el código del control OpcionesBuscar se define un botón de
esta forma:
<Button Name="btnExaminarDir" Grid.Row="2" Grid.Column="4"
Content="Examinar..." />
Que también se podía haber definido de esta otra forma:
<Button Name="btnExaminarDir" Grid.Row="2" Grid.Column="4">
Examinar...
</Button>
En estos dos casos (que son equivalentes), el elemento Button representa un control de
tipo System.Windows.Controls.Button (que es el espacio de nombres de los controles WPF) y
cada uno de los atributos de ese elemento/control son las propiedades del control.
Por ejemplo, el atributo Name es en realidad la propiedad Name del botón, por otro
lado, los tributos Grid.Row y Grid.Column son también propiedades del control
Button, aunque en este caso, a ese tipo de propiedades se las llama
dependency properties o
attached
properties (cuando se decidan a traducir la documentación
de WPF al castellano, puede que use los términos de la traducción, pero por ahora, lo dejo en
inglés, la segunda acepción es menos usada que la primera, así que, seguramente encontrarás más
cosas sobre dependency que sobre attached), y normalmente las distinguirás porque son
propiedades "agregadas" porque ese control (o elemento) está definido dentro de otro elemento (o
control) y puede tomar o asignar los valores de algunos atributos (o propiedades) de ese otro
elemento para asignar ciertas propiedades del control del que depende; para, como en este caso,
indicar en que fila o columna del Grid debe colocarse ese control.
El caso de la "propiedad" Content es un caso especial.
Esa propiedad es la que contiene el contenido del elemento (valga la redundancia) y como en la
mayoría de los casos en XAML, el contenido puede ser cualquier "cosa" (incluso un
elemento/control), y tal como ocurre en este caso en particular, puede ser hasta una cadena de
texto.
Por supuesto, los valores que le podemos asignar a los atributos serán los que a esos
atributos (o propiedades) se puedan asignar, y como norma, esos valores se asignan como cadenas
de texto, después el compilador (o el que se encargue de hacer las validaciones o conversiones)
se encargará de convertir ese valor de texto en el valor adecuado, y si no lo puede asignar,
pues... ya te enterarás porque te avisará con un error.
Bueno, espero que con todo esto que te acabo de explicar tengas un poco más claros los
conceptos de qué es lo que hay detrás de todo ese código XAML que seguramente ahora empezarás a
ver con mayor frecuencia.
De todas formas no te asustes, que no debes saber prácticamente nada de esto que te he
explicado, al menos para poder crear los controles WPF, ya que el diseñador de Visual Studio (o
la herramienta Expression Blend o similares) se encarga de agregar ese código. Pero creo que
siempre es conveniente saber un poco de estas cosas, ya que, (al menos a mi me ocurre), muchas
veces es más fácil hacer pequeños cambios en el código XAML que hacerlo con el diseñador...
En cualquier cosa, como no está de más saberlo, pues te lo he explicado... ya sabes que te avise
antes de que te lo podrías saltar, así que... ahora no te quejes, je, je, je.
Espero que te haya sido útil estas explicaciones.
Nos vemos.
Guillermo