Está en la página 1de 79

Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 1

Desarrollo OOP
Object Oriented Programming

1 Objetivos
Desarrollo de aplicaciones industriales utilizando herramientas de programacin oritentada a objetos

Creacin de aplicaciones con interfaz grfico en Windows

Microsoft Visual Studio Community 2017: IDE gratuito para programacin de aplicaciones .NET
https://www.visualstudio.com/es/downloads/

Confeccin de sistemas Scada para monitorizacin y mando de instalaciones industriales

1.1 Sistemas Scada

Representacin grfica de informacin de planta para supervisin de instalaciones en tiempo real

Posibilidad de actuacin modificando variables de los procesos, activando/desactivando modos de


funcionamiento, etc.

Registro de datos para posterior procesamiento en control de calidad, planificacin de la produccin etc.

Visualizacin de datos recogidos de la planta. Resaltado de informacin importante mediante coloreado


o animaciones

Tratamiento de alarmas
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 2

Visualizacin grfica de histricos


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 3

Sustitucin de paneles de operador tradicionales: flexibilidad, economa, procesado de informacin, etc.

2 Lenguaje C#
Primera versin propuesta por Microsoft en junio del 2000

Lenguaje de programacin orientado a objetos

Utilizado frecuentemente en la actualidad para la programacin de aplicaciones Windows

Sintaxis bsica similar a otros lenguajes de programacin: Java, C++, PHP, etc.

Relacionado con las herramientas del entorno .NET Framework:

- Orientado a la codificacin de aplicaciones robustas y seguras: chequeo de tipos y permisos

- Entorno de ejecucin administrado basado en mquina virtual


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 4

2.1 Generacin y ejecucin de cdigo en .NET

Cdigo Cdigo Cdigo


Otros Visual Basic C#
lenguajes
Compilacin

Cdigo intermedio
IL Intermediate Language

Entorno de ejecucin administrado Common Language


CLR Runtime

JIT Just In Time compiler

Cdigo mquina

En una primera fase de compilacin, el cdigo fuente se traduce a un cdigo IL descrito en un lenguaje
similar a un ensamblador

En la ejecucin del programa en un determinado equipo con una determinada versin de sistema
operativo, se realiza una traduccin a cdigo mquina

Cualquier cambio en el sistema, como modificacin de polticas de seguridad o actualizacin de algn


componente importante, implica que en la siguiente ejecucin habr otra compilacin JIT

Si no se modifica el cdigo IL o la configuracin del equipo, ya no es necesario volver a traducir a


cdigo mquina

Ejemplo:

static void mensaje(int valor) {


// Mtodo 'mensaje', tiene un parmetro 'valor' que es un nmero entero

if (valor == 1) // Si 'valor' es igual a 1 ...

Console.WriteLine("Hola"); // visualiza "Hola" en pantalla

else // Si no ...

Console.WriteLine("Adios"); // visualiza "Adios"

} // Fin del mtodo 'mensaje'

Cdigo IL generado:

.method private hidebysig static void mensaje(int32 'valor') cil managed


{

.maxstack 8 // Pila de tamao mximo para 8 datos

IL_0000: ldarg.0 // Carga en la pila el primer parmetro pasado a 'mensaje'

IL_0001: ldc.i4.1 // Carga en la pila un entero de 4 bytes con el valor 1

IL_0002: bne.un.s IL_000F


// Salta a IL_000F si los dos enteros cargados en la pila son diferentes
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 5

IL_0004: ldstr "Hola" // Carga en la pila la cadena "Hola"

IL_0009: call void [mscorlib]System.Console::WriteLine(string) // Llama a WriteLine

IL_000e: ret // Finaliza la ejecucin del mtodo 'mensaje'

IL_000f: ldstr "Adios" // Carga en la pila la cadena "Adios"

IL_0014: call void [mscorlib]System.Console::WriteLine(string) // Llama a WriteLine

IL_0019: ret // Finaliza la ejecucin del mtodo 'mensaje'


}

En Windows .NET hay un entorno de ejecucin para monitorizar la ejecucin del programa (managed
code) con el objetivo de comprobar su integridad, capturando posibles excepciones o errores y para que
se cumplan las restricciones de seguridad impuestas en su instalacin y relativas a la cuenta de usuario

3 Nmeros enteros

Tipo Tamao Rango


sbyte 8 bits con signo -27 = -128 ... 27-1 = 127

byte 8 bits sin signo 0 ... 28-1 = 255

short 16 bits con signo -215 = -32767 ... 215-1 = 32768

ushort 16 bits sin signo 0 ... 216-1 = 65535

int 32 bits con signo -231 = -2147483648 ... 231-1 = 2147483647

uint 32 bits sin signo 0 ... 232-1 = 4294967295

-263 = -9223372036854775808 ...


long 64 bits con signo
263-1 = 9223372036854775808

ulong 64 bits sin signo 0 ... 264-1 = 18446744073709551615

Sin signo: todos los bits utilizados para expresar el valor en binario

Con signo: en complemento a 2

Ejemplo: 1001011001111001 en 16 bits

- Sin signo = 38521

- Con signo = -27015

3.1 Declaracin de variables

Primero se indica el tipo de datos y a continuacin la variable

Si hay varias variables, se separan por comas

La declaracin finaliza con un punto y coma


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 6

Ejemplos:

C#, Java, PHP, C++, C, etc Visual Basic

int x; Dim x As Integer

int x, y; Dim x, y As Integer

3.2 Conversiones entre diferentes formatos

Conversiones automticas cuando se ampla el formato

int x = 123;
long y = x;

Casting necesario cuando se reduce el formato. El compilador exige que sea el programador quien tome
la responsabilidad de la posible prdida de informacin, obligndole a indicar el casting.

long y = 123;
int x = (int) y;

3.3 Constantes

En hexadecimal si va precedida por 0x, utilizando 4 bits por dgito. Dgitos 0 a 9 y A a F.


Ejemplo: 0xD9 = 1101 1001

Si no, en decimal
Ejemplo: 217 = 1101 1001

4 Enumerados
Se pueden definir tipos de datos enumerados, de forma que una variable de este tipo pueda tomar un
valor dentro de un conjunto posible de valores identificados mediante un nombre

Ejemplo: representacin del estado de un motor

enum Estado { Parado, Acelerando, Marcha, Decelerando, Fallo };


// Definicin del tipo de dato enumerado

Estado estadoMotor = Estado.Parado;


// Declaracin de una variable e inicializacin

Los enumerados son compatibles con los nmeros enteros y cada posible valor de un enumerado
corresponde a un valor entero. Por defecto son valores consecutivos comenzando en 0. Para el caso
anterior, Parado=0, Acelerando=1, Marcha=2, etc

estadoMotor = Estado.Marcha;
int valor = (int)estadoMotor; // Guarda un 2 en valor
estadoMotor = (Estado)3; // Guarda Estado.Decelerando en estadoMotor

Se pueden indicar otros valores enteros en la definicin del enumerado

enum Estado { Parado=10, Acelerando=20, Marcha=30, Decelerando=40, Fallo=0 };


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 7

5 Nmeros reales

Tipo Tamao Rango


float 32 bits -45 38
1.5 * 10 ... 3.4 * 10

double 64 bits -324 308


5.0 * 10 ... 1.7 * 10

decimal 128 bits 96 96 0...28


(-2 ... 2 ) / 10

5.1 float y double

Los valores se pueden indicar en notacin cientfica escribiendo el exponente en base 10 despus de
una E
-5
2.47E-5 = 2.47 * 10

Por defecto, 64 bits en formato double. Ejemplo: double a = 123.5;

Aadir f o F para constantes de 32 bits en formato float. Ejemplo: float b = 123.5f;

Conversiones

Automticas cuando se ampla el formato:


int x = 123;
float a = x;
double b = a + x;

Casting necesario cuando se reduce:


double b = 123;
float a = (float) b;
short s = (short)(a - 1)

Representacin en memoria

Formato IEEE 754 de precisin simple=float o doble=double

En decimal: signo * M * 2E

En formato de precisin simple de 32 bits: sEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM

Bit de signo s. Si s=1, entonces signo=-1. Si s=0, entonces signo=1.

Mantisa M de 23 bits.

Exponente E de 8 bits. Al exponente de rango -126 a 127 se le suma 127 para almacenarlo en el rango
1 a 254.

Ejemplo: float x = -321.6875f;

Es negativo, entonces s=1


8 6 0 -1 -3 -4
321.6875 = 2 + 2 + 2 + 2 + 2 + 2 = 101000001.1011 en binario
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 8

El punto decimal se desplaza hacia la izquierda hasta dejar slo a un 1 en la parte entera:
8
101000001.1011 = 1.010000011011 * 2

M = 010000011011, que se completa hasta 23 bits M = 01000001101100000000000

Exponente E = 8 + 127 = 135 = 10000111 en binario

Representacin en formato IEEE 754: 11000011 10100000 11011000 00000000

Valores especiales

Infinito: S=0, E=255, M=0


-Infinito: S=1, E=255, M=0

Ejemplo: divisin por cero

float x, y, z; // Declara las variables x, y, z como nmeros reales de simple precisin

x = 7.4f; // Asigna el valor 7.4 a la variable x


y = 0.0f; // Asigna el valor 0.0 a la variable y
z = x / y; // Asigna el resultado de la divisin x/y a la variable z

Es posible comprobar si una variable contiene estos valores

if (double.IsPositiveInfinity(z))
System.Console.WriteLine("Resultado = +Infinito");

if (double.IsNegativeInfinity(z))
System.Console.WriteLine("Resultado = -Infinito");

NaN (Not a Number): E=255, M0

Ejemplo: raices cuadradas de nmeros negativos

double x, y; // Declara las variables x, y como nmeros reales de doble precisin

x = -3.0; // Asigna a x el valor -3.0


y = Math.Sqrt(x); // Asigna a y el resultado de la raz cuadrada de x

Es posible inicializar una variable con el valor NaN, por ejemplo, para indicar que no contiene ningn
valor vlido

float z = float.NaN; // Nmero real de simple precisin sin valor vlido


double d = double.NaN; // Nmero real de doble precisin sin valor vlido

Es posible comprobar si una variable contiene un valor vlido

float x = 0, y = 0; // Dos reales de simple precisin inicializados a cero


float z = x / y; // Esta divisin no est definica, genera float.NaN
if (float.IsNaN(z)) // Comprueba si la divisin es NaN
System.Console.WriteLine("Divisin no vlida"); // Mensaje en pantalla

float y double son un valor aproximado

Con 32 o 64 bits es imposible representar los infinitos valores existentes en la recta real

En su lugar, se representan valores aislados en una secuencia en la que estn ms prximos cuanto
menor es su valor absoluto
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 9

Consecuencia: se representan habitualmente valores aproximados y que no son exactos, por lo que no
es conveniente realizar comprobaciones de igualdad entre nmeros reales

Ejemplo: 1.3 * 0.7 es diferente de 0.91

Valor IEEE 754 32 bits Valor aproximado

1.3 00111111101001100110011001100110 1.2999999523162842

0.7 00111111001100110011001100110011 0.699999988079071

1.3 * 0.7 00111111011010001111010111000010 0.9099999666213989

0.91 00111111011010001111010111000011 0.9100000262260437

En la siguiente sentencia if la condicin es falsa

float x, y, z; // Declara las variables x, y, z como nmeros reales de simple precisin

x = 1.3f; // Asigna el valor 1.3 a la variable x


y = 0.7f; // Asigna el valor 0.7 a la variable y
z = 0.91f; // Asigna el valor 0.91 a la variable z

if (z == x * y) ... // Si z es igual a x * y entonces ...

5.2 Tipo decimal

Representacin exacta de nmeros reales, pero con un rango menor

Hasta 28 cifras significativas exactas decimales

Utilizado en aplicaciones financieras y donde sea necesario manejar valores exactos

Es un nmero entero de 96 bits al que se le puede poner un punto decimal para disponer de hasta 28
dgitos decimales

En los bits 0...95 se almacena el nmero entero

En los bits 103...110 se indica el exponente en 8 bits que indica el nmero de dgitos decimales

El bit 96 indica el signo, con 1=negativo, 0=positivo

El resto de bits a cero

Constantes finalizadas con M


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 10

Ejempo:
decimal x = 35.66M;

2
35.66 = 3566 / 10

El nmero entero es 3566 = 110111101110 en binario

El exponente es 2 = 10 en binario

El signo es positivo, 0 en binario

En memoria: 0000...0110111101110 0000000 00000010 00000000 00000000


96 bits 32 bits

5.3 Puntos y comas decimales

- Punto decimal (pases en azul). Ejemplo 1349.86


- Coma decimal (pases en verde). Ejemplo 1349,86

En Espaa la norma oficial es el uso de la coma aunque la RAE indica que hay que tender a la
utilizacin del punto para unificar criterios con otros pases.
En el caso de separadores de millares, se utilizan:

- espacio, en la mayor parte de los pases: 12 390.44

- coma, sobre todo en aplicaciones financieras: 12,390.44

- punto, en Espaa: 12.390,44

- ningn separador, cuando se indican valores numricos en programas: 12390.44

La RAE recomienda tender a utilizar espacios


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 11

6 Problemas causados por manejo inadecuado de las variables


Boeing 787 Dreamline

- El software de control de los generadores de energa elctrica alterna del avin utilizan una variable
entera de 32 bits con signo para contar el nmero de centsimas de segundo transcurridas y as
tener una medida del tiempo.

31
- Esta variable sufre un desbordamiento de formato al cabo de 2 * 1/100 s = 248 das

- Este software, cuando detecta este problema, deshabilita los alternadores y la generacin de
energa elctrica alterna del avin cuando se da este fallo, que se puede producir en pleno vuelo.

- La FAA (Federal Aviation Administration) recomienda apagar completamente el avin al menos


una vez cada 120 das para que no se produzca el fallo.

Ariane 5

- Lanzadera espacial de un slo uso de la ESA (European Space


Agency)

- Puesta en rbita geoestacionaria de hasta 6 toneladas de satlites


comerciales

- En el computador del sistema inercial el programa convierte un


nmero real de 64 bits a un valor entero de 16 bits en el que se
representa la velocidad de desplazamiento horizontal que es
necesario corregir mediante un algoritmo de control.

- Programa desarrollado y probado en Ariane 4 donde funciona


correctamente. Ariane 5 es ms potente: velocidades mayores,
sobrepasamiento del valor mximo 215-1 = 32565.

- El computador del sistema inercial enva datos errneos de


velocidad horizontal al computador de control.

- Integracin del error que genera un valor de actuacin exagerado


que provoca ruptura debido a fuerzas aerodinmicas elevadas.

http://www.rtve.es/noticias/20140604/ecrror-software-convirtio-lanzamiento-espacial-carisimos-
fuegos-artificiales/948262.shtml
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 12

7 Operaciones aritmticas
Con nmeros enteros

Ejemplo: Operacin Ejemplo Resultado


int a, b; Suma a + b 11

a = 7; a - b 3
b = 4; Resta

Multiplicacin a * b 28

Divisin entera a / b 1

Resto a % b 3

Cambio de signo -a -7

Con nmeros reales

Ejemplo:
Operacin Ejemplo Resultado
double x, y; x + y 11.0
Suma
x = 7.0;
y = 4.0; Resta x - y 3.0

Multiplicacin x * y 28.0

Divisin x / y 1.75

Cambio de signo -x -7.0

Combinacin de varios tipos de datos

El formato menor se convierte al mayor y se opera

Ejemplo: a + x

Parntesis

Para modificar el orden de precedencia de operadores

Ejemplo: (a + x) * (y + b)

8 Incrementos y decrementos de nmeros enteros


Operadores ++ y -- para realizar incrementos y decrementos

Ejemplo:

int x, y;

x = 3;
y = 5;
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 13

Operacin Ejemplo Equivalente a Resultado

Incremento x ++; x = x + 1; x = 4

Decremento x --; x = x - 1; x = 2

y = y + 1; x = 24
Incremento previo x = ++y * 4;
x = y * 4; y = 6

x = y * 4; x = 20
Incremento posterior x = y++ * 4;
y = y + 1; y = 6

y = y - 1; x = 16
Decremento previo x = --y * 4;
x = y * 4; y = 4

x = y * 4; x = 20
Decremento posterior x = y-- * 4;
y = y - 1; y = 4

9 Asignaciones con operaciones


Permiten indicar de forma abreviada operaciones donde una misma variable acta como operando y
como receptora del resultado.

Ejemplo:
Operacin Ejemplo Equivalente a

Suma con asignacin x += y; x = x + y;

Resta con asignacin x -= y; x = x - y;

Multiplicacin con asignacin x *= y; x = x * y;

etc

10 Caracteres

Tipo Tamao Rango


char 16 bits Carcter Unicode

Ejemplo: char c = 'A';

Equivalente a: char c = '\x0041';

0x41 = cdigo ASCII del caracter 'A' en hexadecimal

10.1 Tabla ASCII (American Standard Code for Information Interchange)

Asigna un cdigo de 7 bits a cada carcter

Primera parte de la tabla ASCII: cdigos de control, utilizados habitualmente en comunicaciones

Dec Hex ASCII


0 00 NUL (NULl)
1 01 SOH (Start Of Heading)
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 14

2 02 STX (Start Of Text)


3 03 ETX (End of TeXt)
4 04 EOT (End Of Transmission)
5 05 ENQ (ENQuiry)
6 06 ACK (ACKnowledge)
7 07 BEL (BELl)
8 08 BS (BackSpace)
9 09 HT (Horizontal Tab)
10 0A LF (Line Feed)
11 0B VT (Vertical Tab)
12 0C FF (Form Feed)
13 0D CR (Carriage Return)
14 0E SO (Shift Out)
15 0F SI (Shift In)
16 10 DLE (Data Link Escape)
17 11 DC1 (Device Control 1)
18 12 DC2 (Device Control 2)
19 13 DC3 (Device Control 3)
20 14 DC4 (Device Control 4)
21 15 NAK (Negative AcKnowledge)
22 16 SYN (SYNchronous idle)
23 17 ETB (End of Transmission Block)
24 18 CAN (CANcel)
25 19 EM (End of Medium)
26 1A SUB (SUBstitute)
27 1B ESC (ESCape)
28 1C FS (File Separator)
29 1D GS (Group Separator)
30 1E RS (Record Separator)
31 1F US (Unit Separator)
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 15

- Segunda parte de la tabla ASCII: caracteres utilizados para la confeccin de textos en ingls

Caracteres especiales

Dec C# Significado
10 '\n' Nueva lnea
13 '\r' Retorno de carro
9 '\t' Tabulacin horizontal
92 '\\' Barra invertida
39 '\'' Comilla simple
34 '\"' Doble comilla

Ejemplos

"Primera lnea\nSegunda lnea\nTercera lnea"

"Estaban \"dormidos\""
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 16

10.2 Unicode

Necesidad de representar textos en varios idiomas

Espaol ngel, srveme una caa


Chino
Vietnamita Hng c coi l t c vn ny nht
Japons
Cirlico
Griego
rabe
Checo Ahoj, jak se m dnes rno v devt?
Armenio .
Hindi
Sueco Saxon lgt ver nordiska sprken under tiden fr Hansan
etc

Unicode: variantes UTF-8, UTF-16 y UTF-32

UCS (Universal Character Set) y norma ISO 10646

Son normas equivalentes, permiten codificar hasta 231 caracteres diferentes

Por ejemplo, en UTF-8:

- Cada carcter se expresa en 1 a 6 bytes

- Todos los caracteres de la tabla ASCII (0x00 a 0x7F) se expresan en un nico byte

- A partir del cdigo 0x80 hasta el 0x7FFFFFFF se expresan segn la siguiente tabla:

- Ejemplo, el carcter , de cdigo 0xF1 = 1111 0001 se expresa en dos bytes


1100 0011 1011 0001 = 0xC3 0xB1

- Ejemplo, el carcter , de cdigo 0x2260 = 0010 0010 0110 0000 se expresa en tres bytes
1110 0010 1000 1001 1010 0000 = 0xE2 0x89 0xA0

11 Cadenas de caracteres
Concatenacin de varios caracteres para formar un texto

Se manejan mediante objetos inmutables: cualquier modificacin del texto implica la creacin de un
nuevo objeto en memoria
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 17

String cadena; // Declara una cadena de caracteres de cualquier longitud

cadena = "Hola"; // Asignacin de un valor. Se crea un objeto con el valor "Hola"

cadena = cadena + " Pepe";


// Concatenacin de cadenas.
// Crea un objeto en memoria con el valor " Pepe".
// Crea otro objeto en memoria con el valor "Hola Pepe", resultado de la concatenacin

cadena = cadena.ToUpper();
// Aplicacin del mtodo ToUpper() para conversin a maysculas.
// Crea otro objeto con el valor "HOLA PEPE"

Otros mtodos

Index: busca una cadena dentro de otra

IndexAny: busca uno o varios caracteres dentro de una cadena

ToLower: convierte todos los caracteres a minsculas

Trim: elimina espacios al comienzo y al final

StartsWith, EndsWith: indican si una cadena comienza o termina de una determinada forma

Insert: inserta una cadena dentro de otra

Length: obtiene el nmero de caracteres en la cadena

Remove: elimina parte de la cadena

Replace: reemplaza parte de la cadena con otro texto

Split: divide la cadena en partes

Substring: obtiene parte de la cadena

etc.

11.1 Conversin entre cadenas y formatos numricos

Por defecto, el separador decimal es una coma en cadenas para sistemas Windows configurados en
Espaol

String cadena;
double x = 35.2347, y;

cadena = x.ToString(); // Resultado "35,2347"

cadena = String.Format("Temperatura = {0:N2} C, longitud = {1:N1} m.", x, 34);


// Resultado "Temperatura = 35,23 C, longitud = 34,0 m."

cadena = "8.257";
y = Convert.ToDouble(cadena); // Resultado 8257.0
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 18

Si se prefiere utilizar punto decimal en sistemas Windows en Espaol:

double x = Convert.ToDouble("35.2347", CultureInfo.InvariantCulture); // Resultado 35.2347

string cadena = x.ToString(CultureInfo.InvariantCulture); // Resultado "35.2347"

Otras conversiones:

int i = 23;

string s = "376";

float f = (float) 24.35;


// Las constantes con punto decimal son double. Casting para reducir formato de double a float

i = (int) f;
// Casting para reducir formato de float a int

s = i.ToString();
// Todos los tipos disponen del mtodo ToString() para generar una cadena con la
// representacin visual del valor que almacenan

f = Convert.ToSingle(s);
// Clase Convert con mtodos de conversin a diferentes formatos

12 Buleanos

Tipo Tamao Rango

bool 8 bits true o false

No es compatible con ningn formato numrico. No se puede copiar un entero en un buleano ni


viceversa.

12.1 Comparaciones

Generan buleanos

Ejemplo:

int x = 4;
int y = 5; Operacin Ejemplo Resultado

Igual x == y false

Diferente x != y true

Menor x < y true

Menor o igual x <= y true

Mayor o igual x >= y false

Mayor x > y false

El resultado de una comparacin se puede guardar en un buleano:

bool b = x > y;
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 19

12.2 Operadores lgicos

Ejemplo:

bool a = true;
bool b = false; Operacin Ejemplo Resultado

AND a && b false

OR a || b true

NOT ! a false

13 Estructura bsica de un programa


Los algoritmos se describen en mtodos

Los mtodos estn contenidos en clases

Las clases estn contenidas en espacios de nombres

Por ejemplo, para un programa mnimo:

namespace MiEspacio // Espacio de nombres


{
class MiClase // Clase
{
static void Main() // Mtodo
{
System.Console.WriteLine("Hola, mundo"); // Instruccin
}
}
}

El mtodo WriteLine pertenece a la clase Console que est definida en el espacio de nombres System

El sangrado del cdigo suele realizarse de la siguiente forma:


namespace MiEspacio {

class MiClase {

static void Main() {


System.Console.WriteLine("Hola, mundo");
}

}
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 20

14 Espacios de nombres
Permiten organizar los identificadores globales de las clases en una estructura jerrquica

namespace Empresa {

namespace Ingenieria {

class Mantenimiento {
static public string estado() {
return "Reparacin de cinta transportadora";
}
}

class Instalacion {
static public string estado() {
return "Montaje de cadena 4";
}
}

namespace Gestion {

class Ventas {
static public string estado() {
return "Elaboracin de presupuestos";
}

}
}
}

namespace MiEspacio {

class MiPrograma {

static void Main() {


System.Console.WriteLine (Empresa.Ingenieria.Mantenimiento.estado());
System.Console.WriteLine (Empresa.Ingenieria.Instalacion.estado());
System.Console.WriteLine (Empresa.Gestion.Ventas.estado());
}

}
}

14.1 Espacios de nombres predefinidos en .NET Framework

En .NET Framework existen bibliotecas con unas 10000 clases definidas

Espacio de nombres Clases ejemplo Descripcin


System Double, String, Array Tipos bsicos de datos

System.Data DataSet, DataTable Manejo de bases de datos

System.Drawing Brush, Pen, Font Grficos en Windows

System.IO Path, File, Stream Informacin en ficheros


System.Net HttpWebRequest, Dns Solicitudes HTTP

System.Net.Sockets Socket, UdpClient Comunicacin en red

System.Security PermissionSet Seguridad


System.Threading Thread, Monitor Multitarea
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 21

System.Web HttpApplication Servicios Web


System.Windows.Forms Form, TextBox Ventanas y controles

System.XML XmlDataDocument Datos en XML

etc

14.2 Alias

En el caso de que se utilicen dos clases con el mismo nombre, es necesario especificar el espacio de
nombres al que pertenece. Ejemplo:

using System.IO; // Espacio de nombres con clases para entrada/salida con ficheros
using System.Windows.Shapes; // Espacio de nombres con clase para dibujo en ventanas

System.IO.Path rutaFichero;
// Para manejar la ruta para localizar un fichero en una estructura de directorios

System.Windows.Shapes.Path curva; // Para dibujar una curva definida por varios puntos

Alternativamente, se pueden definir alias para no tener que utilizar el espacio nombres:

using IoPath = System.IO.Path;


using WpfPath = System.Windows.Shapes.Path;

IoPath rutaFichero;
WpfPath curva;

15 Estructuras
Son tambin tipos de dato con valor, permiten agrupar varios datos en una nica variable, con la
posibilidad adicional de aadir cdigo en forma de mtodos.

namespace MiEspacio { // Espacio de nombres para esta aplicacin

struct EstructuraPunto { // Define un tipo valor para representar a un punto en 2D

public double x, y;
// Contiene dos nmeros reales de doble precisin para representar sus coordenadas.
// Los miembros x e y se marcan como pblicos para poder utilizarlos
// directamente desde fuera de la estructura.

public EstructuraPunto(double _x, double _y) {


// Constructor para inicializar una nueva estructura a partir de dos valores.
// Se marca como pblico para poder utilizarlo desde cualquier parte del programa.

x = _x; // El primer valor inicializa la coordenada x


y = _y; // y el segundo la coordenada y
}

public double distanciaA(EstructuraPunto p) {


// Mtodo que se ejecuta sobre una estructura para calcular la distancia al
// punto representado por la estructura 'p' pasada por parmetro.
// Se marca como pblico para poder utilizarlo desde cualquier parte del programa.

return Math.Sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));


// Calcula la distancia y la devuelve
}

}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 22

class Programa { // Clase para definir el programa principal

static void Main() { // Mtodo para definir el programa principal

EstructuraPunto a, b;
// Crea dos estructuras, con identificadores 'a' y 'b'.
// Por defecto sus campos 'x' e 'y' se inicializan con valores 0.

a.x = 1;
a.y = 2;
// Da valor a los miembros de la estructura 'a'

b = a; // Copia el valor de la estructura 'a' en la estructura 'b'

b.x = 3;
// Modifica la coordenada 'x' del punto representado por 'b'
// La estructura 'a' no se modifica

b = new EstructuraPunto(4, 5);


// Crea una nueva estructura con x=4, y=5 utilizando el constructor de
// EstructuraPunto y la copia en la estructura 'b'

double d = a.distanciaA(b);
// Pasa la estructura 'b' por valor al mtodo 'distanciaA', que se ejecuta sobre
// la estructura 'a'. Guarda el resultado en 'd'.

} // Fin de Main

} // Fin de la clase Programa

} // Fin del espacio de nombres EN

Cuando se copia una estructura en otra, se copian todos los valores almacenados

Antes de ejecutar la instruccin Despus de ejecutar la instruccin


b = a; b = a;

a b a b

x 1.0 x x 1.0 x 1.0

y 2.0 y y 2.0 y 2.0

16 Tipos referencia - clases


Los tipos referencia se utilizan para crear objetos dinmicamente mediante el operador new.

Las referencias apuntan al objetos que se crean y destruyen durante la ejecucin del programa.

Existe un proceso independiente recolector de basura (garbage collector) encargado de destruir


los objetos no referenciados.
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 23

namespace MiEspacio { // Espacio de nombres para esta aplicacin

class ClasePunto { // Define una clase para representar a un punto en 2D

public double x, y;
// Contiene dos nmeros reales de doble precisin para representar sus coordenadas.
// Los miembros x e y se marcan como pblicos para poder utilizarlos
// directamente desde fuera de la clase.

public ClasePunto(double _x, double _y) {


// Constructor para inicializar un nuevo objeto a partir de dos valores.
// Se marca como pblico para poder utilizarlo desde cualquier parte del programa.

x = _x; // El primer valor inicializa la coordenada x


y = _y; // y el segundo la coordenada y
}

public double distanciaA(ClasePunto p) {


// Mtodo que se ejecuta sobre un objeto para calcular la distancia al
// punto representado por el objeto apuntado por la referencia 'p' pasada por
// parmetro.
// Se marca como pblico para poder utilizarlo desde cualquier parte del programa.

return Math.Sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));


// Calcula la distancia y la devuelve
}

class Program { // Clase para definir el programa principal

static void Main() { // Mtodo para definir el programa principal

ClasePunto a, b;
// Crea dos referencias, con identificadores 'a' y 'b'.
// Por defecto estas referencias valen 'null', indicando que no apuntan a
// ningn objeto

a = new ClasePunto(10, 20);


// La referencia 'a' apunta a un nuevo objeto inicializado con x=10 e y=20

a.x = 1;
a.y = 2;
// Mediante la referencia 'a' podemos modificar los campos pblicos 'x' e 'y'
// del objeto apuntado

b = a; // Hace que la referencia 'b' apunte al mismo objeto apuntado por 'a'

b.x = 3;
// Modifica la coordenada 'x' del punto representado por el objeto apuntado por
// 'b'. La referencia 'a' apunta al mismo objeto, por lo que se est modificando
// el mismo punto

b = new ClasePunto(4, 5);


// Crea un nuevo objeto con x=4, y=5 utilizando el constructor de ClasePunto y
// hace que la referencia 'b' apunte a ese objeto'

double d = a.distanciaA(b);
// Pasa la referencia 'b' por valor al mtodo 'distanciaA', que se ejecuta sobre
// el obejto apuntado por 'a'. Guarda el resultado en 'd'.

} // Fin de Main

} // Fin de la clase Programa

} // Fin del espacio de nombres EN


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 24

Antes de ejecutar la instruccin Despus de ejecutar la instruccin


b = a; b = a;

a b a b

x 1.0 x x 1.0 x

y 2.0 y y 2.0 y

El entorno de ejecucin en Windows .NET dispone de un proceso "recolector de basura" (garbage


collector) encargado de eliminar de memoria los objetos no referenciados

17 Mtodos
17.1 Pase de parmetros por valor

Los parmetros se pasan a los mtodos enviando una copia de su valor

El mtodo maneja el valor pasado en un dato local que desaparece cuando finaliza su ejecucin

using System;

namespace MiEspacio { Al final de la funcin doble:

class MiPrograma {
x 4
static int doble (int dato) {
dato *= 2;
return dato;
} y

static void Main() {


int x = 4; dato 8
int y;
y = doble (x);
}

}
}

17.2 Pase de parmetros por referencia

Utilizado cuando un mtodo tiene que modificar algn dato externo

Al mtodo se le pasa como parmetro una referencia al dato que tiene que modificar
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 25

using System;

namespace MiEspacio {
Al final de la funcin duplica:
class MiPrograma {

static void duplica (ref int dato) { 4


dato = dato * 2;
x
}

static void Main() {


int x = 4;
duplica (ref x); dato
}

}
}

17.3 Pase de parmetros por referencia de datos no inicializados

En el caso de que una referencia apunte a un parmetro no


inicializado, hay que marcarla con out
Al final de la funcin duplica:
using System;

namespace MiEspacio { x 4
class MiPrograma { y 8
static void duplica (int dato, out int doble) {
doble = dato * 2; dato 4
}
doble
static void Main() {
int x = 4, y;
duplica (x, out y);
}

}
}

18 Constructores
Cada clase puede disponer de uno o varios constructores

Permiten indicar cmo se inicializan los objetos a partir de diferentes tipos de fuentes de informacin

Constructor de copia: inicializa un objeto a partir de otro de la misma clase

Marcados con public para poder utilizarlos fuera de la clase donde estn definidos

using System;

namespace MiEspacio {

class Complejo { // Representa a un nmero complejo

public double re, im; // Cada complejo tiene su parte real e imaginaria

// Dato esttico que representa a la raz cuadrada de -1


public static Complejo j = new Complejo(0, 1);

public Complejo() { // Constructor a partir de ninguna informacin


re = im = 0; // Genera un complejo nulo
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 26

public Complejo(double valor) { // Constructor a partir de un nmero real


re = valor; // Crea un complejo sin parte imaginaria
im = 0;
}

public Complejo(double r, double i) { // Complejo a partir de dos nmeros reales


re = r; // El primer parmetro es la parte real
im = i; // y el segundo la imaginaria
}

public Complejo(Complejo c) { // Constructor de copia


re = c.re; // Copia la parte real
im = c.im; // y la imaginaria
}

} // Fin de la clase Complejo

class MiPrograma {

static void Main() {

Complejo a, b, c; // Tres referencias

a = new Complejo(3.2, -5); // Complejo 3.2 - 5 i


b = new Complejo(4); // Complejo 4 + 0 i
c = new Complejo(a); // c es una copia de a
}
}
}

19 Instrucciones
Visual Basic C#, C, C++, Java, PHP, etc
Dim dato, absoluto As Integer int dato, absoluto;

dato = -37 dato = -37;

If dato < 0 Then if (dato < 0)


absoluto = - dato absoluto = - dato;
Else absoluto = dato else absoluto = dato;
End If

Dim i, x As Integer int i, x;

x = 0 x = 0;

For i = 1 To 5 for (i = 1; i <= 5; i ++)


x = x + i x = x + i;
Next i

Dim x As Integer int x;

x = 3 x = 3;

While x > 0 while (x > 0)


x = x - 1 x = x - 1;
End While

Dim x As Integer int x;

x = 3 x = 3;

Do While x > 0 do
x = x - 1 x = x - 1;
Loop while (x > 0);
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 27

19.1 Bloques de instrucciones

Visual Basic C#, C, C++, Java, PHP, etc


Dim x, y, minimo, maximo As Integer int x, y, minimo, maximo;

x = 7 x = 7;
y = 4 y = 4;

If x < y Then if (x < y) {


minimo = x minimo = x;
maximo = y maximo = y;
Else } else {
minimo = y minimo = y;
maximo = x maximo = x;
End If }

20 Definicin de operadores y conversiones automticas


Es posible definir en mtodos estticos cmo se calculan operaciones entre objetos utilizando:

- Operadores binarios:
- Aritmticos: +, -, *, /, %
- Desplazamientos: >>, <<
- Comparacin: >, <, >=, <=, ==, !=
- Lgicos: &, |, ^

- Operadores unarios: +, -, !, ~, ++, --

Con implicit tambin podemos indicar en mtodos estticos cmo se realizan conversiones entre
objetos y otros tipos

Ejemplo: manejo de nmeros complejos

using System;

namespace MiEspacio {

class Complejo { // Representa a un nmero complejo

public double re, im; // Cada complejo tiene su parte real e imaginaria

// Dato esttico que representa a la raz cuadrada de -1


public static Complejo j = new Complejo(0, 1);

public Complejo() { // Constructor a partir de ninguna informacin


re = im = 0; // Genera un complejo nulo
}

public Complejo(double valor) { // Constructor a partir de un nmero real


re = valor; // Crea un complejo sin parte imaginaria
im = 0;
}

public Complejo(double r, double i) { // Complejo a partir de dos nmeros reales


re = r; // El primer parmetro es la parte real
im = i; // y el segundo la imaginaria
}

public Complejo(Complejo c) { // Constructor para crear un complejo a partir de otro


re = c.re; // Copia la parte real
im = c.im; // y la imaginaria
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 28

public static Complejo operator + (Complejo c1, Complejo c2) {


// Definicin de la suma entre dos complejos c1 y c2 para generar otro complejo

return new Complejo(c1.re + c2.re, c1.im + c2.im);


// Devuelve un nuevo complejo utilizando un constructor
}

public static Complejo operator - (Complejo c1, Complejo c2) { // Definicin de la resta
return new Complejo(c1.re - c2.re, c1.im - c2.im);
}

public static Complejo operator - (Complejo c1) { // Definicin del cambio de signo
return new Complejo(- c1.re, - c1.im);
}

public static Complejo operator * (Complejo c1, Complejo c2) { // Multiplicacin


return new Complejo(c1.re * c2.re - c1.im * c2.im, c1.re * c2.im + c1.im * c2.re);
}

public static Complejo operator / (Complejo c1, Complejo c2) { // Divisin


double denominador = c2.re * c2.re + c2.im * c2.im;
return new Complejo(
(c1.re * c2.re + c1.im * c2.im) / denominador,
(-c1.re * c2.im + c1.im * c2.re) / denominador );
}

public static implicit operator Complejo (double d) { // Conversin de real a complejo


return new Complejo(d); // Genera el complejo utilizando un constructor
}

public static Complejo operator ~ (Complejo c1) { // Definicin del complejo conjugado
return new Complejo(c1.re, -c1.im); // Cambio de signo en parte imaginaria
}

} // Fin de la clase Complejo

class MiPrograma {

static void Main() {

Complejo a, b, c, d;

a = new Complejo(3.2, -5); // Complejo 3.2 - 5 i


b = new Complejo(4); // Coplejo 4 + 0 i
c = new Complejo(a); // c es una copia de a

d = c - (~a + 4.5) / (3 * Complejo.j - b);


}

} // Fin de la clase MiPrograma


} // Fin del espacio de nombres

21 Matrices
Son tipos referencia, por lo que es necesario crearlas dinmicamente en una instruccin del programa
mediante el uso del operador new

Los subndices siempre comienzan en 0

Ejemplos:

int[] m = new int [10]; // Matriz unidimensional de 10 enteros


int i;

for (i = 0; i < m.Length; i ++) // m.Length es el nmero de elementos = 10


m[i] = i * 10; // Asigna valores 0, 10, 20, ...
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 29

float[,] m2 = new float [2,3]; // Matriz bidimensional de 2 filas y 3 columnas

int j;
for (i = 0; i < m2.GetLength(0); i ++) // i recorre las filas, de 0 a 1
for (j = 0; j < m2.GetLength(1); j ++) // j recorre las columnas, de 0 a 2
m2[i,j] = i * 10 + j;

Hay que tener en cuenta que se manejan mediante referencias

int[] m1 = new int[10]; // Crea una matriz de 10 enteros apuntada por la referencia 'm1'
int[] m2; // Referencia 'm2' que no apunta a ninguna matriz por ahora

m1[0] = 1234; // Carga el valor 1234 en la primera posicin de la matriz apuntada por 'm1'
m2 = m1; // La referencia 'm2' apunta a la misma matriz apuntada por 'm1'
m2[0] = -123; // Sustituye el valor 1234 en la pimera posicin de la matriz por el valor -123

21.1 Instruccin foreach

Utilizada para recorrer matrices y otros tipos de contenedores de informacin

using System;

namespace MiEspacio {

class MiPrograma {

static int maximo (int[] matriz) { // Devuelve el valor mximo encontrado en la matriz
int resultado = matriz[0]; // El primer candidato es el primer dato
foreach (int dato in matriz) // Para cada dato almacenado en la matriz ...
if (dato > resultado) // Si es mayor que el candidato ...
resultado = dato; // Actualiza el resultado
return resultado; // Devuelve el resultado
}

static void Main() {

int[] m = new int[10]; // Crea una matriz de 10 elementos

// Solicita 10 valores por teclado y los guarda en la matriz


for (int i = 0; i < m.Length; i ++) {
Console.Write ("Elemento {0}: ", i);
m[i] = Convert.ToInt32 (Console.ReadLine ());
}

int max = maximo (m); // Calcula el mximo


Console.WriteLine ("Mximo = {0}", max); // y lo visualiza
}

}
}

22 Colecciones
Permiten acumular un nmero indeterminado de objetos y datos

Diferentes posibilidades en cuanto a su organizacin interna: listas, rboles, diccionarios, etc.

Existen clases predefinidas en .NET Framework para el manejo de varios tipos de colecciones

22.1 Listas

using System; // Espacio de nombres de la clase Console


using System.Collections.Generic; // Espacio de nombres de la clase List
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 30

namespace Listas {

class Programa {

static void Main(string[] args) {

List<string> lista = new List<string>(); // Crea una lista de cadenas

lista.Add("Blgica"); // Aade elementos a la lista


lista.Add("Luxemburgo");
lista.Add("Austria");
lista.Add("Italia");

Console.WriteLine("En posicin 1: " + lista[1]); // Visualiza "Luxemburgo"

lista.Sort(); // Ordena la lista alfabeticamente

Console.WriteLine("Con bucle for:");


for (int i = 0; i < lista.Count; i++) // Recorre la lista con bucle for
Console.WriteLine(" " + lista[i]);

Console.WriteLine("Con bucle foreach:");


foreach (string pais in lista) // Recorre la lista con bucle foreach
Console.WriteLine(" " + pais);

// Busca un elemento en la lista y lo sustituye por otro


if (lista.Contains("Italia")) {
int posicion = lista.BinarySearch("Italia");
Console.WriteLine("Italia est en la posicin " + posicion.ToString());
lista[posicion] = "Grecia";
Console.WriteLine("Italia sustituido por Grecia");
} else Console.WriteLine("Italia no est en la lista");

string[] matriz = new string[] { "Per", "Nicaragua", "Guatemala" };


List<string> americanos = new List<string>(matriz);
// Convierte una matriz en una lista

lista.AddRange(americanos);
// Aade los elementos de una lista al final de otra lista

string[] m = lista.ToArray();
// Convierte una lista en una matriz

lista.Insert(1, "Noruega");
// Inserta un nuevo elemento en una posicin

lista.Remove("Guatemala"); // Elimina un elemento de la lista


lista.RemoveAt(2); // Elimina un elemento que ocupa una posicin

lista.Add("Noruega");
lista.Add("Austria"); // Una lista puede tener elementos repetidos

lista = lista.Distinct().ToList(); // Elimina elementos repetidos

}
}
}

22.2 Diccionarios

Conjunto de entradas que relacionan una clave con un valor

using System;
using System.Collections.Generic;

namespace MiEspacio {

class MiClase {

static void Main() {


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 31

Dictionary<string,string> diccionario = new Dictionary<string,string>();


// Diccionario que lleva una cadena a otra cadena

diccionario["cosa"] = "Objeto inanimado, por oposicin a ser viviente";


diccionario["objeto"] =
"Aquello que sirve de materia o asunto al ejercicio de las facultades mentales";
diccionario["algo"] = "Designa lo que no se quiere o no se puede nombrar";
diccionario["trasto"] = "Cosa intil, estropeada, vieja o que estorba mucho";
// Aade entradas en el diccionario

Console.WriteLine("Significado de objeto = {0}", diccionario["objeto"]);


// Muestra la clave de una entrada

}
}
}

Los diccionarios pueden relacionar valores de tipos diferentes, incluso objetos:

using System;
using System.Collections.Generic;

namespace MiEspacio {

class Coordenadas { // Cada objeto representa a unas coordenadas geogrficas

public double latitud, longitud;


// Cada punto geogrfico tiene su latitud y su longitud

public Coordenadas (double lat, double lon) { // Constructor


latitud = lat;
longitud = lon;
}

public string aCadena() { // Conversin a cadena


return latitud.ToString() + " N, " + longitud.ToString() + " W";
}
}

class MiClase {

static void Main() {

Dictionary<string,Coordenadas> posiciones = new Dictionary<string, Coordenadas>();


// Diccionario que lleva el nombre de una ciudad a sus coordenadas geogrficas

posiciones["Vigo"] = new Coordenadas(42.23, -8.72);


posiciones["Redondela"] = new Coordenadas(42.42,-8.64);
posiciones["Ponteareas"] = new Coordenadas(42.17, -8.50);
posiciones["Cambados"] = new Coordenadas(42.51, -8.81);
// Aade ciudades y coordenadas

if (posiciones.ContainsKey("Redondela"))
Console.WriteLine("Coordenadas de Redondela = {0}",
posiciones["Redondela"].aCadena());
else Console.WriteLine("No tengo las coordenadas de Redondela");
// Muestra las coordenadas de Redondela

string ciudadesAlNDeVigo = "";


foreach (string ciudad in posiciones.Keys) {
if (posiciones[ciudad].latitud > posiciones["Vigo"].latitud)
ciudadesAlNDeVigo += ciudad + " ";
}
Console.WriteLine("Ciudades al N de Vigo = " + ciudadesAlNDeVigo);
// Lista de ciudades al N de Vigo

posiciones.Remove("Ponteareas"); // Elimina la entrada de Ponteareas del diccionario


}}}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 32

23 Propiedades
Los objetos puede disponer propiedades para que podamos intercambiar informacin con ellos
mediante operaciones de lectura/escritura de forma similar a como se maneja una variable

La ventaja es que podemos controlar cmo se realizan esas lecturas y escrituras mediante la definicin
de las operaciones get y set para cada propiedad en la clase correspondiente

En una clase se suelen definir datos privados que slo se pueden manejar desde los mtodos y
propiedades de esa clase. Mediante propiedades pblicas podemos controlar cmo se realizan las
operaciones de lectura/escitura sobre los datos

Las propiedades para las cuales no se define la accin set, son propiedades de slo lectura. Si no se
define la accin get, son propiedades de slo escritura

Ejemplo:

namespace MiEspacio {

class Media { // Clase para obtener la media de vaios valores numricos

private double suma; // Va a almacenar la suma de todos los valores


private uint cuantos; // Cuenta el nmero de valores

public Media () { // Constructor


suma = cuantos = 0; // Inicializa la suma y el contador de valores
}

public double Otro { // Propiedad para aadir un nuevo valor

set { // Define la operacin de escritura sobre esta propiedad


suma += value; // Acumula el valor
cuantos ++; // Indica que hay un nuevo valor
}

public double Resultado { // Propiedad para obtener la media

get { // Se define la operacin de lectura del resultado


if (cuantos > 0) // Si hay algn dato ...
return suma / cuantos; // devuelve la media
else return 0; // si no, devuelve un cero
}

} // Fin de la clase 'Media'

class Programa {

static void Main(string[] args) {

Media m = new Media (); // Crea un nuevo objeto 'Media'

m.Otro = 3; // Aade el valor 3


m.Otro = 7; // Aade el valor 7
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 33

Console.WriteLine (m.Resultado);
// Calcula y lee el resultado, mostrndolo en pantalla

} // Fin de la clase 'Programa'

} // Fin del espacio de nombres 'MiEspacio'

24 Control de errores de ejecucin: excepciones


Los programas tienen que capturar y tratar las excepciones generadas cuando se producen errores de
ejecucin para evitar que el sistema operativo finalice su ejecucin

Ejemplo:

class Program {

static double introduceDouble() {


// Introduce un nmero real por teclado y lo devuelve

string cadena = System.Console.ReadLine();


// Introduce por teclado en una cadena

double valor = Double.Parse(cadena);


// La convierte a nmero real

return valor; // Devuelve el nmero real


}

static double introduceTemperatura() {


// Introduce un valor de temperatura ambiente por teclado y lo devuelve.
// Se considera vlida si est entre -100 y 70.
// Devuelve NaN si no es vlida.

System.Console.Write("Temperatura ambiente = ");


// Visualiza un mensaje en pantalla

double temperatura = introduceDouble();


// Introduce la temperatura por teclado

if (temperatura < -100 || temperatura > 70) // Si no es vlida


temperatura = Double.NaN; // indica que no hay valor vlido

return temperatura;
// Devuelve el resultado
}

static void Main(string[] args) {

double T;

T = introduceTemperatura(); // Solicita una temperatura

if (Double.IsNaN(T)) // Si no es vlida

System.Console.WriteLine("Error: Temperatura errnea");


// Indica que hay un error

else System.Console.WriteLine("Temperatura introducida = " + T);


// Si no, muestra la temperatura en pantalla
}
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 34

Manejo de excepciones en lenguajes de programacin orientados a objetos:

- Intento de ejecucin de un bloque de instrucciones mediante la sentencia try

- Captura de errores de ejecucin mediante un bloque catch

- Lanzamiento de excepciones mediante la sentencia throw

- Propagacin de excepciones

Ejemplo:

class Program {

static double introduceDouble() {


// Introduce un nmero real por teclado y lo devuelve

string cadena = System.Console.ReadLine();


// Introduce por teclado en una cadena

double valor = Double.Parse(cadena);


// La convierte a nmero real

return valor; // Devuelve el nmero real


}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 35

static double introduceTemperatura() {


// Introduce un valor de temperatura ambiente por teclado y lo devuelve.
// Se considera vlida si est entre -100 y 70.
// Devuelve NaN si no es vlida.

System.Console.Write("Temperatura ambiente = ");


// Visualiza un mensaje en pantalla

double temperatura = introduceDouble();


// Introduce la temperatura por teclado

if (temperatura < -100 || temperatura > 70) // Si no es vlida

throw new Exception("Temperatura fuera de rango");


// Lanza una excepcin con un mensaje asociado

return temperatura;
// Devuelve el resultado
}

static void Main(string[] args) {

double T;

try { // Intenta la ejecucin del siguiente bloque de instrucciones

T = introduceTemperatura(); // Solicita una temperatura

System.Console.WriteLine("Temperatura introducida = " + T);


// Si no, muestra la temperatura en pantalla

} catch (Exception ex) { // Si salta alguna excepcin ...

System.Console.WriteLine("Error: " + ex.Message);


// Visualiza por pantalla el mensaje asociado a la excepcin

T = Double.NaN; // Marca temperatura no vlida


}

}
}

25 Herencia
Se puede crear una nueva clase derivada que hereda todo lo definido en otra clase base

Los constructores de las clases derivadas tienen que llamar en primer trmino a algn constructor de la
clase base utilizando la palabra reservada base

Los mtodos virtual de una clase base se pueden redefinir en una clase derivada utilizando el mismo
identificador y parmetros y marcndolos con override

Los mtodos redefinidos suelen hacer uso del mismo mtodo de la clase base. Para ello se utiliza la
palabra reservada base

Los miembros privados de la clase base se pueden utilizar en las clases derivadas marcndolos con
protected
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 36

Existe una clase Object predefinida que acta como clase base para todas las clases utilizadas en el
programa. Dispone de un mtodo virtual ToString(), que se puede redefinir en cualquier clase para
convertir un objeto a cadena de caracteres, por ejemplo, para visualizarlo en pantalla

Ejemplo:

using System;

namespace MiEspacio {

class Punto { // Representa a un punto en 2D

protected double x, y;
// Coordenadas del punto. Protegidas para que no puedan modificarse
// fuera de la clase ni de clases derivadas de esta.

public Punto(double cx, double cy) { // Constructor


x = cx;
y = cy;
}

public Punto(Punto p) { // Constructor de copia


x = p.x;
y = p.y;
}

public void traslada(Punto vector) {


// Mtodo de traslacin, donde se utiliza un vector de traslacin

x += vector.x;
y += vector.y;
}

public virtual void escala(double e) { // Aplicacin de un factor de escala e


x *= e;
y *= e;
}

public double leeX() { // Para poder leer la coordenada x desde otras clases
return x;
}

public double leeY() { // Para poder leer la coordenada x desde otras clases
return y;
}

public override string ToString() { // Conversin de punto a cadena


return "Punto en (" + x.ToString() + ", " + y.ToString() + ")";
}

class Linea : Punto {


// Representa a una lnea entre dos puntos
// Recibe mediante herencia las coordenadas del punto origen

Punto desplazamiento;
// Aade un vector de desplazamiento para obtener el otro extremo de la lnea

public Linea(float ox, float oy, float dx, float dy) : base(ox, oy) {
// Constructor
// Lnea situada en (ox, oy) y con vector de desplazamiento (dx, dy)
// Llama al constructor de la clase base para inicializar la posicin

desplazamiento = new Punto(dx, dy); // Crea el vector de desplazamiento


}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 37

public override void escala(double e) { // Escalado por un factor e


base.escala(e); // Llama al mismo mtodo de la clase base para escalar el origen
desplazamiento.escala(e); // Aplica el factor de escala al vector de desplazamiento
}

public override string ToString() { // Conversin a cadena


return "Lnea en (" + x.ToString() + ", " + y.ToString() +
") y desplazamiento (" + desplazamiento.leeX().ToString() + "," +
desplazamiento.leeY().ToString() + ")";
}
}

class Circulo : Punto {


// Un crculo situado en un punto y con un radio
// Su posicin la recibe mediante herencia del punto

protected double radio; // Aade un radio

public Circulo(float ox, float oy, float r) : base(ox, oy) {


// Constructor
// Crculo en (ox, oy) y radio r
// Llama al constructor de la clase base para inicializar su posicin

radio = r; // Inicializa su radio


}

public override void escala(double e) { // Escalado por el factor e


base.escala(e); // Aplica escalado la posicin, llamando al mismo mtodo de Punto
radio *= e; // Escala el radio
}

public override string ToString() { // Conversin a cadena


return "Crculo de centro (" + x.ToString() + ", " + y.ToString() +
") y radio " + radio.ToString();
}
}

class Arco : Circulo {


// Arco situado en un punto, con un radio y un ngulo inicial y final
// Recibe del crculo su posicin y radio

float anguloInicial, anguloFinal; // Aade los ngulos inicial y final

public Arco(float cx, float cy, float r, float ai, float af) : base(cx, cy, r) {
// Constructor
// Arco en (cx, cy), radio r y ngulos ai y af
// Llama al constructor del crculo para inicializar su posicin y radio

anguloInicial = ai; // Inicializa ngulo inicial


anguloFinal = af; // Inicializa ngulo final
}

public override string ToString() { // Conversin a cadena


return "Arco de centro (" + x.ToString() + ", " + y.ToString() +
"), radio " + radio.ToString() + " ngulo inicial " + anguloInicial.ToString() +
" y ngulo final " + anguloFinal.ToString();
}
}

class MiPrograma {

static void Main() {

Punto p = new Punto(3, 3);


Linea l = new Linea(2, 0, 5, -5);
Circulo c = new Circulo(4, 4, 1);
Arco a = new Arco(5, 5, 2, 0, 90);

Console.WriteLine(p.ToString());
Console.WriteLine(l.ToString());
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 38

c.traslada(p);
Console.WriteLine(c.ToString());

a.traslada(p);
a.escala(0.5);
Console.WriteLine(a.ToString());
}
}
}

25.1 Jerarqua de clases en WPF Windows Presentation Foundation

Clases relacionadas mediante herencia utilizadas para el manejo de interfaces grficas

26 Clases abstractas y polimorfismo


Una clase abstracta contiene uno o varios mtodos abstractos, marcados con la palabra reservada
abstract

En la clase abstracta, los mtodos abstractos estn declarados y no definidos, es decir, para cada
mtodo abstracto se indica un identificador, un tipo de valor de retorno y una lista de parmetros, no se
definen sus instrucciones

Los mtodos abstractos actan como mtodos virtuales cuyas instrucciones se pueden redefinir en
clases derivadas

Se utilizan para modelar comportamientos comunes para diferentes tipos de objetos


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 39

Ejemplo:

using System;

namespace MiEspacio {

abstract class Animal {


public abstract string Sonido();
}

class Gato : Animal {


public override string Sonido() {
return "Miau";
}
}

class Perro : Animal {


public override string Sonido() {
return "Guau";
}
}

class MiPrograma {

static void Main() {


Animal[] animales = new Animal[4];
animales[0] = new Gato ();
animales[1] = new Gato ();
animales[2] = new Perro ();
animales[3] = new Gato ();
foreach (Animal a in animales)
Console.WriteLine (a.Sonido ());
}

}
}

Otro ejemplo:

using System;
using System.Collections.Generic;

namespace MiEspacio {

class Punto { // Representa a un punto en 2D

protected double x, y;
// Coordenadas del punto. Protegidas para que puedan modificarse
// slo en esta clase y en clases derivadas

public Punto(double cx, double cy) { // Constructor


x = cx;
y = cy;
}

public Punto(Punto p) { // Constructor de copia


x = p.x;
y = p.y;
}

public void traslada(Punto vector) {


// Mtodo de traslacin, donde se utiliza un vector de traslacin

x += vector.x;
y += vector.y;
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 40

public virtual void escala(double e) { // Aplicacin de un factor de escala e


x *= e;
y *= e;
}

public double leeX() { // Para poder leer la coordenada x desde otras clases
return x;
}
public double leeY() { // Para poder leer la coordenada x desde otras clases
return y;
}

public override string ToString() { // Conversin de punto a cadena


return "Punto en (" + x.ToString() + ", " + y.ToString() + ")";
}

abstract class ElementoGrafico {


// Clase abstracta para modelar todas las caractersticas comunes a diferentes
// elementos grficos

protected Punto posicion;


// Todos los elementos grficos tienen una posicin en el plano

public ElementoGrafico(double ox, double oy) {


// Constructor para inicializar la posicin

posicion = new Punto(ox, oy);


}

public virtual void traslada(Punto vector) {


// Mtodo utilizado por defecto para trasladar cualquier elemento grfico

posicion.traslada(vector); // Traslada su posicin


}

public virtual void escala(double e) { // Escalado de un elemento grfico


posicion.escala(e); // Escala suposicin
}

public abstract override string ToString();


// Conversin de un elemento grfico a cadena.
// Marcado como virtual porque hay que definirlo en cada clase derivada.
// Marcado con override porque sustituye al mismo mtodo de la clase Object

public abstract double superficie();


// Obtiene la superficie de un elemento grfico.
// Hay que definirlo en cada clase derivada para cada tipo de elemento.

class Linea : ElementoGrafico {


// Representa a una lnea entre dos puntos
// Recibe mediante herencia las coordenadas del punto origen

Punto desplazamiento;
// Aade un vector de desplazamiento para obtener el otro extremo de la lnea

public Linea(float ox, float oy, float dx, float dy) : base(ox, oy) {
// Constructor
// Lnea situada en (ox, oy) y con vector de desplazamiento (dx, dy)
// Llama al constructor de la clase base para inicializar la posicin

desplazamiento = new Punto(dx, dy); // Crea el vector de desplazamiento


}

public override void escala(double e) { // Escalado por un factor e


base.escala(e); // Llama al mismo mtodo de la clase base para escalar el origen
desplazamiento.escala(e); // Aplica el factor de escala al vector de desplazamiento
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 41

public override string ToString() { // Conversin a cadena


return "Lnea en (" + posicion.leeX().ToString() + ", " + posicion.leeY().ToString() +
") y desplazamiento (" + desplazamiento.leeX().ToString() + "," +
desplazamiento.leeY().ToString() + ")";
}

public override double superficie() { // Clculo de la superficie


return 0; // Una lnea no tiene superficie
}
}

class Circulo : ElementoGrafico {


// Un crculo situado en un punto y con un radio
// Su posicin la recibe mediante herencia del punto

protected double radio; // Aade un radio

public Circulo(float ox, float oy, float r) : base(ox, oy) {


// Constructor
// Crculo en (ox, oy) y radio r
// Llama al constructor de la clase base para inicializar su posicin

radio = r; // Inicializa su radio


}

public override void escala(double e) { // Escalado por el factor e


base.escala(e); // Aplica escalado la posicin, llamando al mismo mtodo de Punto
radio *= e; // Escala el radio
}

public override string ToString() { // Conversin a cadena


return "Crculo de centro (" + posicion.leeX().ToString() + ", " +
posicion.leeY().ToString() + ") y radio " + radio.ToString();
}

public override double superficie() { // Clculo de la superficie del crculo


return Math.PI * radio * radio;
}
}

class Arco : Circulo {


// Segmento de arco situado en un punto, con un radio y un ngulo inicial y final
// Recibe del crculo su posicin y radio

float anguloInicial, anguloFinal; // Aade los ngulos inicial y final

public Arco(float cx, float cy, float r, float ai, float af) : base(cx, cy, r) {
// Constructor
// Arco en (cx, cy), radio r y ngulos ai y af
// Llama al constructor del crculo para inicializar su posicin y radio

anguloInicial = ai; // Inicializa ngulo inicial


anguloFinal = af; // Inicializa ngulo final
}

public override string ToString() { // Conversin a cadena


return "Arco de centro (" + posicion.leeX().ToString() + ", " +
posicion.leeY().ToString() + "), radio " + radio.ToString() +
" ngulo inicial " + anguloInicial.ToString() +
" y ngulo final " + anguloFinal.ToString();
}

public override double superficie() {


// Calcula la superficie del segmento de arco
// Es la superficie de todo el crculo, pero troceada segn los ngulos inicial y final

return base.superficie() * (anguloFinal - anguloInicial) / 360;


}
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 42

class Dibujo : ElementoGrafico {


// Un dibujo como una coleccin de uno o varios elementos grficos

List<ElementoGrafico> elementos;
// Los elementos grficos que componen el dibujo se manejan en una lista

public Dibujo() : base(0, 0) {


// Constructor
// Se llama al constructor de Elemento grfico para establecer una posicin (0, 0)
// El dibujo no maneja posicin, cada elemento grfico tiene su propia posicin

elementos = new List<ElementoGrafico>(); // Crea la lista


}

public void carga(ElementoGrafico elemento) {


// Carga un nuevo elemento grfico en el dibujo

elementos.Add(elemento);
}

public override string ToString() {


// Convierte el dibujo a cadena
// Mediante polimorfismo acumula las cadenas generadas al convertir todos sus elementos

string resultado = "";


foreach (ElementoGrafico elemento in elementos) // Recorre todos los elementos
resultado += elemento.ToString() + " "; // Los separa con varios espacios
return resultado.Trim(); // Elimina los espacios sobrantes al final
}

public override void traslada(Punto vector) {


// Traslada un dibujo
// Mediante polimorfismo llama la mtodo de traslacin de todos sus elementos

foreach (ElementoGrafico elemento in elementos)


elemento.traslada(vector);
}

public override void escala(double e) {


// Escala un dibujo
// Mediante polimorfismo llama al mtodo de escalado de todos sus elementos

foreach (ElementoGrafico elemento in elementos)


elemento.escala(e);
}

public override double superficie() {


// Calcula la superficie de un dibujo
// Mediante polimorfismo llama al mtodo de clculo de la superficie de todos sus
// elementos

double resultado = 0;
foreach (ElementoGrafico elemento in elementos)
resultado += elemento.superficie();
return resultado;
}

class MiPrograma {

static void Main() {

Linea l = new Linea(2, 0, 5, -5);


Circulo c = new Circulo(4, 4, 1);
Arco a = new Arco(5, 5, 2, 0, 90);

Dibujo d1 = new Dibujo();


d1.carga(l);
d1.carga(c);
d1.carga(a);

Console.WriteLine("d1 = " + d1.ToString());


Console.WriteLine();
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 43

Console.WriteLine("Superficie d1 = " + d1.superficie());


Console.WriteLine();

Dibujo d2 = new Dibujo();


d2.carga(d1);
d2.carga(new Circulo(2, 2, 1));
d2.escala(2);

Console.WriteLine("d2 = " + d2.ToString());


Console.WriteLine();
Console.WriteLine("Superficie d2 = " + d2.superficie());
Console.WriteLine();

}
}

27 Interfaces
Una clase puede ser clase derivada de otra clase base. No puede ser derivada de varias clases base.

La herencia mltiple se puede implantar mediante interfaces. Una clase puede implantar varias
interfaces.

Una interfaz slo puede contener declaraciones (cabeceras sin instrucciones) de mtodos y de
propiedades, todos pblicos. No puede contener datos.

Ejemplo:

using System;

namespace MiEspacio {

interface IComunicacion {
string Sonido ();
}

interface IAlimentacion {
string Alimento ();
}

class Gato : IComunicacion, IAlimentacion {


string IComunicacion.Sonido () {
return "Miau";
}
string IAlimentacion.Alimento () {
return "Pescado";
}
}

class Perro : IComunicacion, IAlimentacion {


string IComunicacion.Sonido () {
return "Guau";
}
string IAlimentacion.Alimento () {
return "Carne";
}
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 44

class MiPrograma {

static void Main() {


IComunicacion[] animales = new IComunicacion[4];
animales[0] = new Gato();
animales[1] = new Gato();
animales[2] = new Perro();
animales[3] = new Gato();
foreach (IComunicacion c in animales)
Console.WriteLine (c.Sonido() + ", " +
((IAlimentacion)c).Alimento());
}

}
}

28 WPF - Windows Presentation Foundation


Conjunto de recursos de programacin para la creacin de interfaces de usuario en aplicaciones
Windows ejecutadas en la plataforma .NET

- Herramientas visuales de diseo

- Espacios de nombres con multitud de clases predefinidas

- Controles utilizados habitualmente como mens, botones, etc.

- Conexin con fuentes de datos

- Aceleracin de grficos mendiante DirectX. Soporte para animaciones y 3D

- Localizacin y dimensiones de componentes basados en su contenido

- Reproduccin de audio y video

- Definicin declarativa de la interfaz con el usuario mediante archivos en formato XAML


(Extensible Application Markup Language)

28.1 Densidad de puntos

La misma aplicacin se puede ejecutar en pantallas ms grandes o ms pequeas y con densidades


de puntos de 96 dpi (dots per inch, puntos por pulgada) o de 120 dpi, por ejemplo

En WPF las unidades se expresan en puntos correspondientes a una pantalla de 96 dpi

Ejemplo: una pantalla de 19 pulgadas con una resolucin de 1600x1200 puntos tiene una densidad de
puntos:
1600 + 1200
= 100
19
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 45

Esto significa que todos los elementos visuales de la aplicacin se van a mostrar con unas
dimensiones ligeramente ms pequeas en esta pantalla

Para que esto no suceda, en Windows se puede modificar el DPI utilizado por defecto. Esto se configura
yendo al escritorio y luego con el botn derecho Personalizar - Pantalla - Establecer tamao de texto
personalizado

28.2 Versin de .NET Framework

Es una parte del sistema operativo con herramientas para la generacin y ejecucin de aplicaciones,
bibliotecas de clases predefinidas y funcionalidades diferentes segn su versin

Cuando elaboramos una nueva aplicacin en Visual Studio, es necesario indicar para qu version de
.NET Framework vamos a preparar el programa

28.3 XML - Extended Markup Language

Es un lenguaje de descripcin de informacin desarrollado por el W3C (World Wide Web Consortium)

En un archivo de texto se describe toda la informacin, utilizando para ello etiquetas tags y atributos

Las etiquetas permiten establecer una organizacin en rbol. Dentro de cada etiqueta se pueden
establecer atributos

- Ejemplo: fichero con datos sobre varias personas, utilizando las etiquetas datos, persona, dni, nombre,
direccion, email

<?xml version="1.0" encoding="utf-8"?>


<datos>
<persona>
<dni>123456</dni>
<nombre>Ana</nombre>
<direccion>Vigo</direccion>
<email>ana@ejemplo.com</email>
</persona>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 46

<persona>
<dni>654321</dni>
<nombre>Juan</nombre>
<direccion>Monforte</direccion>
<email>juan@ejemplo.com</email>
</persona>
</datos>

- Conversin de la etiqueta dni en un atributo


<?xml version="1.0" encoding="utf-8"?>
<datos>
<persona dni="123456">
<nombre>Ana</nombre>
<direccion>Vigo</direccion>
<email>ana@ejemplo.com</email>
</persona>

<persona dni="654321">
<nombre>Juan</nombre>
<direccion>Monforte</direccion>
<email>juan@ejemplo.com</email>
</persona>
</datos>

Descripcin de toda la informacin en atributos:


<?xml version="1.0" encoding="utf-8"?>
<datos>
<persona dni="123456" nombre="Ana" direccion="Vigo" email="ana@ejemplo.com" />
<persona dni="654321" nombre="Juan" direccion="Monforte" email="juan@ejemplo.com" />
</datos>

En XML se utilizan espacios de nombres para diferenciar etiquetas que pueden utilizar el mismo
identificador pero que tienen diferente significado. Ejemplo:

<?xml version="1.0" encoding="utf-8"?>


<datos>
<persona>
<nombre>Ana</nombre>
<edad>30</edad>
<email>ana@ejemplo.com</email>
<mascota>
<especie>perro</especie>
<nombre>Trosky</nombre>
<edad>3</edad>
</mascota>
</persona>
</datos>

En esta informacin XML, las etiquetas nombre y edad tienen diferente significado segn el nivel dnde
se utilizan. Se pueden diferenciar claramente si pertenecen a espacios de nombres distintos
<?xml version="1.0" encoding="utf-8"?>
<datos xmlns:per="http://ejemplo.com/persona" xmlns:mas="http://ejemplo.com/mascota">
<per:persona>
<per:nombre>Ana</per:nombre>
<per:edad>30</per:edad>
<per:email>ana@ejemplo.com</per:email>
<mas:mascota>
<mas:especie>perro</mas:especie>
<mas:nombre>Trosky</mas:nombre>
<mas:edad>3</mas:edad>
</mas:mascota>
</per:persona>
</datos>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 47

Cada espacio de nombres xmlns (XML name space) tiene un identificador (ejemplo: per) y una cadena
de caracteres nica (ejemplo: ="http://ejemplo.com/persona") que lo identifica. Esta cadena suele ser
un URI (Universal Resource Identifier) en el que se utiliza un nombre de dominio nico contratado en
Internet

Los espacios de nombres tambin se pueden aplicar si la informacin est descrita en atributos:

<?xml version="1.0" encoding="utf-8"?>


<datos xmlns:per="http://ejemplo.com/persona" xmlns:mas="http://ejemplo.com/mascota">
<per:persona per:nombre="Ana" per:edad="30" per:email="ana@ejemplo.com">
<mas:mascota mas:especie="perro" mas:nombre="Trosky" mas:edad="3" />
</per:persona>
</datos>

28.4 XAML

Extended Application Marckup Language

Basado en XML

El objetivo es separar el diseo grfico del cdigo que rige la lgica del programa. De esta forma, los
diseadores grficos pueden trabajar de forma independiente de los programadores, incluso con otras
herramientas de diseo

Cada etiqueta XAML corresponde a una clase con el mismo nombre. Por ejemplo, la etiqueta Button
corresponde a la clase Button en el programa

Si una etiqueta est contenida en otra, los correspondientes elementos visuales estn contenidos uno
dentro del otro

Las propiedades de cada elemento se indican mediante atributos o con etiquetas adicionales

La etiqueta general es de tipo Window, donde se


definen espacios de nombres XML y el ttulo y
dimensiones de la ventana

Dentro hay una etiqueta que indica el uso de algn


contenedor, por ejemplo Grid, que permite definir
una interfaz organizada de forma tabular y
estableciendo mrgenes entre componentes para
situarlos en una posicin determinada

Ejemplo:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1" x:Class="WpfApp1.MainWindow"
Title="MainWindow" Height="177" Width="282">

<Grid>

<Label x:Name="etiquetaDato" Content="Introduce un dato:"


HorizontalAlignment="Left" Margin="16,25,0,0" VerticalAlignment="Top"/>

<TextBox x:Name="editorDato" HorizontalAlignment="Left" Height="23"


Margin="130,29,0,0" TextWrapping="Wrap" VerticalAlignment="Top"
Width="120"/>

<Button x:Name="botonDuplica" Content="Duplica" HorizontalAlignment="Left"


Margin="85,65,0,0" VerticalAlignment="Top" Width="75"
Click="botonDuplica_Click"/>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 48

<Label x:Name="etiquetaResultado" Content="Resultado:"


HorizontalAlignment="Left" Margin="47,102,0,0" VerticalAlignment="Top" />

</Grid>

</Window>

Para cada componente, se puede indicar mediante el atributo x:Name el identificador que se utilizar en
el programa para la referencia que apuntar al objeto correspondiente

Para el caso de los componentes Label y Button, el texto que se muestra sobre el componente se
establece en el atributo Content

Mediante HorizontalAlignment y VerticalAlignment se indica cmo se sita el componente en su


contenedor

Utilizando el atributo Margin, se pueden establecer mrgenes izquierdo, superior, derecho, inferior

En el caso del botn, en el atributo Click se indica que cuando el usuario pulse con el ratn, el evento
correspondiente lo atender el mtodo botonDuplica_Click

Este archivo XAML se puede editar, pero lo habitual es utilizar el diseador de interfaces para generarlo
automticamente, para establecer las propiedades de cada componente:

y para elegir qu eventos se van a tratar en el programa y con qu mtodos


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 49

En el proyecto se crea un archivo fuente para que podamos definir el comportamiento del programa
mediante mtodos en C#
using System;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
// Con estas sentencias using se puede acceder a las clases definidas dentro
// de estos espacios de nombres

namespace WpfApp1 {

public partial class MainWindow : Window {


// El cdigo de manejo de la aplicacin se define en una clase derivada de Window

public MainWindow() { // Constructor: se ejecuta al comienzo del programa


InitializeComponent(); // Crea los componentes descritos en el archivo XAML
}

private void botonDuplica_Click(object sender, RoutedEventArgs e) {


// Atiende al evento que se produce cuando se pulsa el botn

int x = Convert.ToInt32(editorDato.Text);
// Recoge el texto escrito en el editor donde se indica el dato a duplicar
// y lo convierte a nmero entero de 32 bits

x = x * 2;
// Lo duplica

etiquetaResultado.Content = "Resultado: " + x.ToString();


// Muestra el resultado, aadiendo el dato duplicado
}

}
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 50

Normalmente las aplicaciones hay que protegerlas frente a la introduccin de datos incorrectos que
pueden provocar excepciones que finalizan la ejecucin del programa de forma inesperada:

Para ello se pueden activar/desactivar ciertos componentes dependiendo de si el dato introducido es


correcto o no. Por ejemplo, atendiendo al evento TextChanged del editor, que se produce cada vez que
hay una modificacin del dato:

private void editorDato_TextChanged(object sender, TextChangedEventArgs e) {


// Atiende al evento TextChanged, que se produce cada vez que se modifica el texto

try { // Intenta la ejecucin de ...

int x = Convert.ToInt32(editorDato.Text);
// Convierte el texto a nmero entero

botonDuplica.IsEnabled = true;
editorDato.Foreground = Brushes.Black;
// Si no hay problemas en la conversin, habilita el botn de duplicado y
// establece color negro para el texto del editor

}
catch (Exception ex) { // Si hubo algn problema en la conversin ...

botonDuplica.IsEnabled = false;
editorDato.Foreground = Brushes.Red;
// Deshabilita el botn de duplicado y establece color rojo para el texto
// del editor
}

}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 51

29 Distribucin Layout
Existen varios tipos de componentes contenedores que permiten disponer otros componentes en su
interior, para poder organizar la interfaz con el usuario

Cada componente tiene una serie de propiedades que indican cmo se distribuyen en su contenedor

HorizontalAlignment, VerticalAlignment: alineacin centrada, izquierda, derecha, arriba, abajo o por


defecto ocupando todo el espacio disponible en el contenedor.

Ejemplo: HorizontalAlignment="Left"

Margin: separacin con respecto a los bordes del contenedor.

Ejemplo: Margin="10,20,30,40" para 10 puntos izquierda, 20 arriba, 30 derecha y 40 abajo


Ejemplo: Margin="10" para 10 puntos en todas direcciones

Padding: establece mrgenes internos dentro del componente

MinWidth, MinHeight, MaxWidth, MaxHeight: dimensiones mnimas y mximas de un componente, de


forma que puede adaptarse a cambios de tamao del contenedor. Por ejemplo, cuando el usuario
cambia el tamao de la ventana.

Width, Height: establecen unas dimensiones determinadas

30 Contenedores
Las dimensiones y la posicin de los componentes dentro del contenedor se ajustan en funcin de las
dimensiones del contenedor, aplicando unas reglas que dependen del tipo de contenedor:

30.1 Grid

Organizacin en formato tabla, con todos los elementos situados en filas y columnas.
Por defecto hay nicamente una fila y columna

<Grid x:Name="tabla">
</Grid>

Se pueden definir colecciones de filas y columnas y situar otros controles en la posicin deseada
Por ejemplo: tres filas y dos columnas

<Grid x:Name="tabla">

<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<Label Content="Celda 1,1" FontSize="20" FontFamily="Arial" VerticalAlignment="Center"


HorizontalAlignment="Center" Grid.Row="1" Grid.Column="1" />
<Label Content="Celda 2,0" FontSize="20" FontFamily="Arial" VerticalAlignment="Center"
HorizontalAlignment="Center" Grid.Row="2" Grid.Column="0" />

</Grid>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 52

Las filas y columnas se pueden dimensionar con un tamao fijo o indicar con un * que se ocupar el
resto del espacio disponible. Tambin se puede indicar que ajusten su tamao a su contenido mediante
Auto

<Grid>

<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>

<Rectangle Fill="Pink" Margin="0" Grid.Row="0" Stroke="Black"/>


<Rectangle Fill="Gold" Margin="0" Grid.Row="1" Stroke="Black"/>
<Rectangle Fill="Yellow" Margin="0" Grid.Row="2" Stroke="Black"/>
<Rectangle Fill="GreenYellow" Margin="0" Grid.Row="3" Stroke="Black"/>

<Label Grid.Row="0" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"


FontSize="20" FontFamily="Arial" Content="Fila de 100 puntos de alto" />
<Label Grid.Row="1" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"
FontSize="20" FontFamily="Arial" Content="Alto ajustado al contenido" />
<Label Grid.Row="2" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"
FontSize="20" FontFamily="Arial" Content="Alto de 2*" />
<Label Grid.Row="3" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"
FontSize="20" FontFamily="Arial" Content="Alto de 3*" />

</Grid>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 53

30.2 StackPanel

Varios componentes organizados en horizontal o en vertical

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">


<Button Margin="10" Padding="5" FontSize="20" Content="Primero" />
<Button Margin="10" Padding="5" FontSize="20" Content="Segundo" />
<Button Margin="10" Padding="5" FontSize="20" Content="Tercero" />
</StackPanel>

Ejemplo con dos StackPanel combinados

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">

<Button Margin="10" Padding="5" FontSize="20" Content="Primero" HorizontalAlignment="Left"


VerticalAlignment="Top" />

<StackPanel Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top">


<Button Margin="10" Padding="5" FontSize="20" Content="Segundo 1" />
<Button Margin="10" Padding="5" FontSize="20" Content="Segundo 2" />
<Button Margin="10" Padding="5" FontSize="20" Content="Segundo 3" />
</StackPanel>

<Button Margin="10" Padding="5" FontSize="20" Content="Tercero" />

</StackPanel>

30.3 Canvas

Los componentes se sitan estableciendo una posicin absoluta con respecto al origen, utilizando los
atributos Canvas.Top y Canvas.Left

<Canvas >
<Label FontSize="20" Content="Dato" Canvas.Left="40" Canvas.Top="30"/>
<TextBox FontSize="20" Canvas.Left="98" Canvas.Top="35" Width="120"/>
<Button FontSize="15" Content="Introducir" Canvas.Left="120" Canvas.Top="80" Width="75"/>
</Canvas>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 54

30.4 Dockpanel

Todos los componentes se ajustan contra los bordes del contenedor y ocupan todo su espacio

Ejemplo:

<DockPanel LastChildFill="True">

<StackPanel DockPanel.Dock="Bottom" HorizontalAlignment="Right" Orientation="Horizontal">

<Button Margin="10,10,2,10" Padding="3">Aceptar</Button>

<Button Margin="2,10,10,10" Padding="3">Cancelar</Button>

</StackPanel>

<TextBox DockPanel.Dock="Top" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto"


AcceptsReturn="True" Margin="10">Esto es un texto</TextBox>

</DockPanel>

En el TextBox se pueden escribir varias lneas y se


puede mostrar una barra de desplazamiento vertical
utilizando las propiedades TextWrapping,
VerticalScrollBarVisibility y AcceptsReturn

En el contenedor de tipo DockPanel, la propiedad


LastChildFill hace que el ltimo componente (en este
ejemplo, el TextBox), rellene el espacio restante

En el contenedor de tipo StackPanel, se indica para sus componentes (dos botones) una organizacin
horizontal y alineada a la derecha. Tambin se indica que ocupa la posicin inferior en el DockPanel

30.5 ScrollViewer

Cuando hay que mostrar demasiada informacin, es til poder disponer de barras de desplazamiento

Ejemplo:

<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">

<Button Margin="10" Padding="5" FontSize="20" Content="Primero" />


<Button Margin="10" Padding="5" FontSize="20" Content="Segundo" />
<Button Margin="10" Padding="5" FontSize="20" Content="Tercero" />
<Button Margin="10" Padding="5" FontSize="20" Content="Cuarto" />
<Button Margin="10" Padding="5" FontSize="20" Content="Quinto" />
<Button Margin="10" Padding="5" FontSize="20" Content="Sexto" />
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 55

</StackPanel>

</ScrollViewer>

31 Controles comunes
31.1 Label

Para mostrar texto no editable en una lnea

El texto se indica en la propiedad Content

<Label Content="Esto es un texto" HorizontalAlignment="Left" Margin="298,30,0,0"


VerticalAlignment="Top"/>

31.2 TextBlock

Para mostrar texto con posibilidad de utilizar diferentes juegos de caracteres, texto multilnea, etc.

<TextBlock HorizontalAlignment="Left" Margin="315,136,0,0" TextWrapping="Wrap"


VerticalAlignment="Top">

<Run Text="Primera lnea"/><LineBreak/>


<Run Text="Segunda lnea"/><LineBreak/>
<Run/><LineBreak/>
<Run Text="Otra lnea"/>
</TextBlock>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 56

Si es necesario aadir un borde y una barra de desplazamiento:

<Border BorderThickness="1" Margin="315,136,0,0"


HorizontalAlignment="Left"
VerticalAlignment="Top" BorderBrush="#FF9C9C9C">

<ScrollViewer>

<TextBlock TextWrapping="Wrap" Width="100"


Height="100" Margin="5">
<Run Text="Primera lnea"/><LineBreak/>
<Run Text="Segunda lnea"/><LineBreak/>
<Run/><LineBreak/>
<Run Text="Otra lnea"/>
</TextBlock>

</ScrollViewer>

</Border>

31.3 Button

Botones para ejecutar ciertas acciones cuando el usuario hace click con el ratn

El texto que se muestra sobre el botn se indica en la propiedad Content

Se puede habilitar o deshabilitar mediante la propiedad IsEnabled

<Button x:Name="miBoton" Content="Botn" HorizontalAlignment="Left" Margin="411,70,0,0"


VerticalAlignment="Top" Width="75" Click="miBoton_Click"/>

Cuando se pulsa el botn, se genera un evento Click para el que preparamos un mtodo

private void miBoton_Click(object sender, RoutedEventArgs e) {


// Aqu se escribe el algoritmo a ejecutar cuando se pulsa el botn
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 57

31.4 TextBox

Para solicitar informacin al usuario, recogindola en una cadena de caracteres

El texto se maneja en la propiedad Text

<TextBox x:Name="editorDato" HorizontalAlignment="Left" Height="23" Margin="411,32,0,0"


TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>

private void miBoton_Click(object sender, RoutedEventArgs e) {


// Atiende al evento Click sobre el botn

double dato = Convert.ToDouble(editorDato.Text);


// Recoge el dato del TextBox y lo convierte a nmero real
}

31.5 CheckBox

Una casilla con un texto que se puede marcar o desmarcar. El texto se indica en la propiedad Content.

En la propiedad IsChecked podemos consultar su estado

Cuando el usuario pulsa el CheckBox para cambiar su estado, se produce el evento Click

void actualizaSeleccionados() {
// Actualiza el texto de la etiqueta donde se muestran qu CheckBox estn marcados

etiquetaSeleccionados.Content = "Marcados: "; // Texto inicial fijo

if ((bool)checkPrimero.IsChecked) // Aade un 1 si el primero est marcado


etiquetaSeleccionados.Content += "1 ";

if ((bool)checkSegundo.IsChecked) // Aade un 2 si el segundo est marcado


etiquetaSeleccionados.Content += "2 ";

if ((bool)checkTercero.IsChecked) // Aade un 3 si el tercero est marcado


etiquetaSeleccionados.Content += "3";
}

private void checkPrimero_Click(object sender, RoutedEventArgs e) {


// Atiende al evento Click sobre el primer CheckBox
actualizaSeleccionados();
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 58

private void checkSegundo_Click(object sender, RoutedEventArgs e) {


// Atiende al evento Click sobre el segundo CheckBox
actualizaSeleccionados();
}

private void checkTercero_Click(object sender, RoutedEventArgs e) {


// Atiende al evento Click sobre el tercero CheckBox
actualizaSeleccionados();
}

31.6 RadioButton

Eleccin de una opcin entre varias opciones excluyentes

En la propiedad IsChecked se puede comprobar si una opcin est activada

Todas las opciones relacionadas entre s se incluyen dentro del mismo contenedor. Por ejemplo, dentro
de un StackPanel:

<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,10,0,0">

<RadioButton x:Name="radioRadianes" HorizontalAlignment="Left" VerticalAlignment="Top"


Content="Radianes"/>

<RadioButton x:Name="radioGrados" HorizontalAlignment="Left" VerticalAlignment="Top"


Content="Grados"/>

</StackPanel>

private void miBoton_Click(object sender, RoutedEventArgs e) {


// Atiende al evento Click sobre el botn

double anguloGrados;

if ((bool)radioRadianes.IsChecked) // Si se han seleccionado radianes ...

anguloGrados = Convert.ToDouble(editorDato.Text) * 180.0 / Math.PI;


// convirtelos a grados

else anguloGrados = Convert.ToDouble(editorDato.Text);


// si no, recoge los grados

etiquetaAngulo.Content = "ngulo en grados: " + String.Format("{0:N2}", anguloGrados);


// Visualiza el ngulo con dos decimales en la etiqueta
}

31.7 ListBox

Permite mostrar varios elementos (etiquetas, checkbox, etc.) en una lista y seleccionar uno o varios.

En la propiedad SelectionMode podemos indicar cuntos elementos se pueden seleccionar.


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 59

En la propiedad Items indicamos la lista de elementos. Es una coleccin de objetos.

En la propiedad SelectedItem recogemos el elemento seleccionado, en SelectedIndex la posicin en la


lista (comenzando en el ndice 0).

Para cada item, la propiedad IsChecked indica si est seleccionado.

El evento SelectionChanged se produce cada vez que el usuario modifica la seleccin en la lista.

<ListBox x:Name="listaProvincias" HorizontalAlignment="Left" Margin="10,10,0,0"


VerticalAlignment="Top" SelectionChanged="listaProvincias_SelectionChanged" >
<ListBoxItem Content="A Corua"/>
<ListBoxItem Content="Lugo"/>
<ListBoxItem Content="Ourense"/>
<ListBoxItem Content="Pontevedra"/>
</ListBox>
<Label x:Name="etiquetaProvincia" Content="Label" HorizontalAlignment="Left"
Margin="10,90,0,0" VerticalAlignment="Top"/>

private void listaProvincias_SelectionChanged(object sender, SelectionChangedEventArgs e) {


// Evento que se provoca cuando se modifica la seleccin en la lista

if (listaProvincias.SelectedItem != null) { // Si se ha seleccionado algn elemento ...

ListBoxItem item = (ListBoxItem)listaProvincias.SelectedItem; // Obtn el elemento

etiquetaProvincia.Content = "Provincia: " + item.Content;


// Muestra la provincia en la etiqueta
}
}
}

31.8 ComboBox

Similar a ListBox, pero mostrando una lista desplegable

Las opciones mostradas como etiquetas de texto


corresponden a ComboBoxItem
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 60

<ComboBox x:Name="comboProvincias" HorizontalAlignment="Left" Margin="21,10,0,0"


VerticalAlignment="Top" Width="120" SelectedIndex="0"
SelectionChanged="comboProvincias_SelectionChanged">
<ComboBoxItem Content="A Corua"/>
<ComboBoxItem Content="Lugo"/>
<ComboBoxItem Content="Ourense"/>
<ComboBoxItem Content="Pontevedra"/>
</ComboBox>

<Label x:Name="etiquetaProvincia" Content="Label" HorizontalAlignment="Left"


Margin="164,8,0,0" VerticalAlignment="Top"/>

private void comboProvincias_SelectionChanged(object sender, SelectionChangedEventArgs e) {


// Evento que se provoca cuando se modifica la seleccin en la combo

if (comboProvincias.SelectedItem != null) { // Si se ha seleccionado algn elemento ...

ComboBoxItem item = (ComboBoxItem)comboProvincias.SelectedItem; // Obtn el elemento


etiquetaProvincia.Content = "Provincia: " + item.Content; // Muestra la provincia
}
}

31.9 Slider

El usuario puede arrastrar un cursor a lo largo de una lnea para establecer un valor.

En la propiedad Orientation se indica si va a ser horizontal o vertical.

En la propiedad Value podemos obtener el valor actual.

En Minimum y Maximum podemos indicar los valores en los extremos.

Cuando el usuario realiza cualquier modificacin del valor, se genera el evento ValueChanged.

Ejemplo: una etiqueta muestra el valor establecido en el slider, entre 0 y 100%

<Slider x:Name="entrada" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"


Width="159" Minimum="0" Maximum="100" ValueChanged="entrada_ValueChanged" Height="23"
SmallChange="1"/>

<Label x:Name="etiquetaValor" Content="Valor: 0%" HorizontalAlignment="Left"


Margin="188,7,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.368,0.077"/>

private void entrada_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {


// Atiende al evento ValueChanged que se produce cada vez que el usuario modifica la posicin
// del Slider

etiquetaValor.Content = String.Format("Valor: {0:N2}%", entrada.Value);


// Convierte el valor a formato numrico con dos decimales y lo integra en una cadena
// para mostrarlo en una etiqueta
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 61

31.10 Image

Visualizacin de archivos de imagen en formatos habituales *.bmp, *.jpg, *.png, etc

Para poder distribuir las imgenes con la aplicacin desarrollada, es conveniente


incluir la imagen como recurso en el proyecto. Para ello hay que ir al explorador de
soluciones, hacer click con el botn derecho en el proyecto y aadir la imagen:
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 62

En la propiedad Build Action del archivo de imagen, hay que elegir


la opcin Resource

Ahora ya podemos aadir un control de tipo Image y elegir el


archivo utilizando la propiedad Source
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 63

<Image HorizontalAlignment="Left" Height="232" Margin="10,10,0,0" VerticalAlignment="Top"


RenderOptions.BitmapScalingMode="HighQuality" Width="118" Source="deposito.png"/>

Es conveniente establecer el atributo RenderOptions.BitmapScalingMode="HighQuality" para que la


imagen no pierda calidad despus de un escalado

31.11 Rectangle

Zona rectangular donde se puede definir un color de fondo

Propiedades Width y Height para establecer ancho y alto en puntos.

Estructura Margin para establecer la posicin con respecto a su contenedor. En esta estructura hay
propiedades Top, Left, Right, Bottom para establecer mrgen superior, izquierdo, derecho e inferior.

Ejemplo: dibujar rectngulos que indican la cantidad de producto que hay en un depsito en funcin de
la posicin de un Slider

<Image x:Name="imagenDeposito" HorizontalAlignment="Left" Height="239" Margin="16,17,0,0"


VerticalAlignment="Top" Width="123" Source="deposito.png"/>

<Rectangle x:Name="rectanguloProducto" HorizontalAlignment="Left" Height="112"


Margin="38,106,0,0" VerticalAlignment="Top" Width="14" Fill="#FF3D7FDE"/>

<Rectangle x:Name="rectanguloFondo" HorizontalAlignment="Left" Height="76" Margin="38,30,0,0"


VerticalAlignment="Top" Width="14" Fill="#FF595859"/>

<Slider x:Name="entrada" HorizontalAlignment="Left" Margin="170,29,0,0"


VerticalAlignment="Top" Width="28" Maximum="100" ValueChanged="entrada_ValueChanged"
Orientation="Vertical" Height="189"/>

private void entrada_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {


// Atiende al evento ValueChanged que se produce cada vez que el usuario modifica la posicin
// del Slider

double escalaY = (rectanguloFondo.Height + rectanguloProducto.Height) /


(entrada.Maximum - entrada.Minimum);
// Escala para pasar del rango del Slider al rango de puntos en vertical en el dibujo

rectanguloFondo.Height = (entrada.Maximum - (entrada.Value - entrada.Minimum)) * escalaY;


rectanguloProducto.Height = (entrada.Value - entrada.Minimum) * escalaY;
// Establece la altura de los rectngulos del producto y del fondo

Thickness margenes = rectanguloProducto.Margin;


margenes.Top = rectanguloFondo.Margin.Top + rectanguloFondo.Height;
rectanguloProducto.Margin = margenes;
// Modifica el mrgen superior del rectngulo del producto para situarlo en el dibujo
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 64

31.12 Mens

Coleccin de MenuItem que pueden ser opciones terminales o submens que son a su vez colecciones
de MenuItem

Cuando el usuario elige una opcin terminal, se produce el evento Click sobre el MenuItem

<Menu HorizontalAlignment="Left" Height="22" VerticalAlignment="Top" >


<MenuItem Header="_Fichero">
<MenuItem Header="_Nuevo" Click="FicheroNuevo_Click"/>
<MenuItem Header="_Abrir" Click="FicheroAbrir_Click"/>
<MenuItem Header="_Guardar" Click="FicheroGuardar_Click"/>
<MenuItem Header="Guardar _como" Click="FicheroGuardarComo_Click"/>
<MenuItem x:Name="FicheroGuardarAutomaticamente" Header="Guardar au_tomticamente"
IsCheckable="True" Click="FicheroGuardarAutomaticamente_Click"/>
<Separator />
<MenuItem Header="_Salir" Click="FicheroSalir_Click" />
</MenuItem>
<MenuItem Header="_Ayuda" Click="Ayuda_Click"/>
</Menu>

private void FicheroSalir_Click(object sender, RoutedEventArgs e) {


// Se ejecuta cuando el usuario elige la opcin Salir del submen Fichero

MessageBox.Show("Se ha elegido Salir", "Informacin"); // Muestra un mensaje en una nueva


ventana
Application.Current.Shutdown(); // Finaliza la ejecucin del programa
}

private void FicheroNuevo_Click(object sender, RoutedEventArgs e) {


MessageBox.Show("Se ha elegido Fichero - Nuevo", "Informacin");
}

private void FicheroAbrir_Click(object sender, RoutedEventArgs e) {


MessageBox.Show("Se ha elegido Fichero - Abrir", "Informacin");
}

private void FicheroGuardar_Click(object sender, RoutedEventArgs e) {


MessageBox.Show("Se ha elegido Fichero - Guardar", "Informacin");
}

private void FicheroGuardarComo_Click(object sender, RoutedEventArgs e) {


MessageBox.Show("Se ha elegido Fichero - Guardar como", "Informacin");
}

private void Ayuda_Click(object sender, RoutedEventArgs e) {


MessageBox.Show("Se ha elegido Ayuda");
}

private void FicheroGuardarAutomaticamente_Click(object sender, RoutedEventArgs e) {


// Se ejecuta cuando el usuario pulsa sobre la opcin "Guardar automticamente"

// Muestra un mensaje indicando si se activ o no


if (FicheroGuardarAutomaticamente.IsChecked)
MessageBox.Show("Guardado automtico activado", "Informacin");
else MessageBox.Show("Guardado automtico desactivado", "Informacin");
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 65

31.13 Iconos

Se pueden incorporar como recursos para poder utilizarlos en diferentes partes de la aplicacin:

- Icono para la aplicacin, que aparecer cuando se instala, cuando se minimiza y en la barra superior.

- Iconos utilizados en los mens.

- Barras de herramientas que suelen situarse debajo del men.

- etc.

En el proyecto de la aplicacin se puede crear un directorio de iconos, pinchando con el botn derecho
sobre el proyecto y Add - New Folder, y luego se pueden aadir con Add - Existing Item

<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 66

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication3"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Icon="iconos/aplicacion.ico">

<StackPanel Orientation="Vertical" Background="#FFF0F0F0">

<Menu HorizontalAlignment="Left" Height="22" VerticalAlignment="Top" >


<MenuItem Header="_Fichero">
<MenuItem Header="_Nuevo" Click="FicheroNuevo_Click">
<MenuItem.Icon>
<Image Source="iconos/nuevo.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Abrir" Click="FicheroAbrir_Click" >
<MenuItem.Icon>
<Image Source="iconos/abrir.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Guardar" Click="FicheroGuardar_Click">
<MenuItem.Icon>
<Image Source="iconos/guardar.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Guardar _como" Click="FicheroGuardarComo_Click"/>
<MenuItem Header="Guardar automticamente" IsCheckable="True"
Click="FicheroGuardarAutomaticamente_Click"
x:Name="FicheroGuardarAutomaticamente"/>
<Separator />
<MenuItem Header="_Salir" Click="FicheroSalir_Click" >
<MenuItem.Icon>
<Image Source="iconos/salir.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_Ayuda" Click="Ayuda_Click"/>
</Menu>

<ToolBarTray >
<ToolBar>
<Button ToolTip="Crea un documento nuevo" Click="FicheroNuevo_Click">
<Image Source="iconos/nuevo.png" />
</Button>
<Button ToolTip="Abre un documento" Click="FicheroAbrir_Click">
<Image Source="iconos/abrir.png" />
</Button>
<Button ToolTip="Guarda el documento" Click="FicheroGuardar_Click">
<Image Source="iconos/guardar.png" />
</Button>
</ToolBar>
<ToolBar>
<Button ToolTip="Salir de la aplicacin" Click="FicheroSalir_Click">
<Image Source="iconos/salir.png" />
</Button>
</ToolBar>
</ToolBarTray>

</StackPanel>

</Window>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 67

32 Eventos
El grueso del cdigo de las aplicaciones corresponden a mtodos que se activan mediante eventos

- Eventos relacionados con el ciclo de vida del programa:

Initialized: el componente se ha inicializado

Loaded: adems de inicializado, al componente se le han aplicado estilos y relaciones con datos

Activated:en el caso de una ventana, cuando se muestra por primera vez o cuando el usuario
cambia de ventana y la activa

Deactivated: cuando el usuario cierra una ventana o selecciona otra

Unloaded: cuando se destruye el componente, ya sea porque se ha eliminado de su contenedor o


porque el contenedor se ha cerrado

Closed: cuando se cierra definitivamente una ventana. Puede servir para guardar el estado de la
aplicacin en un archivo para poder recuperarla en una ejecucin posterior.

etc.

- Eventos relacionados con el teclado:

KeyDown, KeyUp: cuando se pulsa o deja de pulsar una tecla

TextInput: cuando la pulsacin de una tecla ha modificado un texto en un componente


etc.

- Eventos relacionados con el ratn:

MouseLeftButtonDown, MouseRightButtonDown, etc.

- etc

Ejemplo:

<Canvas x:Name="canvas" Background="Aqua" MouseDown="Canvas_MouseDown" Loaded="Canvas_Loaded">


</Canvas>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 68

Polyline polilinea = new Polyline();


// Crea un objeto para representar varias lineas que conectan varios puntos

private void Canvas_MouseDown(object sender, MouseButtonEventArgs e) {


// Atiende al evento de click de ratn sobre el canvas

Point punto = e.GetPosition(this); // Obtiene la posicin del ratn


polilinea.Points.Add(punto); // Aade el punto a la polilnea
}

private void Canvas_Loaded(object sender, RoutedEventArgs e) {


// Atiende el evento producido cuando se inicializa el canvas

polilinea.Stroke = Brushes.Black; // Color de dibujo


polilinea.StrokeThickness = 3; // Grosor de la polilnea
canvas.Children.Add(polilinea); // Aade la polilnea al canvas
}

33 Temporizaciones
Se pueden crear temporizadores para ejecutar cdigo cuando transcurre un cierto intervalo de tiempo.

Ejemplo: un segundero

namespace WpfApplication1 {

public partial class MainWindow : Window {

public MainWindow() {
InitializeComponent();
}

int segundos = 0; // Cuenta nmero de segundos transcurridos

System.Windows.Threading.DispatcherTimer temporizador;
// Objeto para implantar temporizaciones

private void Window_Loaded(object sender, RoutedEventArgs e) {


// Atiende al evento Loaded sobre la ventana de la aplicacin. Se produce al comienzo
// de la ejecucin del programa, una vez se han inicializado todos los recursos de la
// ventana

temporizador = new System.Windows.Threading.DispatcherTimer();


// Crea el objeto temporizador

temporizador.Tick += new EventHandler(temporizador_Tick);


// Indica que el evento que se produce al final de cada temporizacin se atiende
// mediante el mtodo temporizador_Tick

temporizador.Interval = new TimeSpan(0, 0, 0, 1, 0);


// La propiedad Interval del temporizador es un objeto de la clase TimeSpan donde
// se indica el intervalo de temporizacin en das, horas, minutos, segundos y
// milisegundos. En este caso las temporizaciones son de 1 segundo.

temporizador.Start();
// Arranca el temporizador
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 69

private void temporizador_Tick(object sender, EventArgs e) {


// Atiende al evento que se produce al final de cada temporizacin
// Incrementa el contador de segundos y lo visualiza en una etiqueta

segundos++;
etiquetaTiempo.Content = "Tiempo = " + segundos.ToString() + " s.";
}
}
}

34 Grficas
Para generar grficas que muestran la evolucin temporal de una o varias variables de un proceso, se
puede utilizar un Canvas donde se pueden mostrar elementos grficos generados dinmicamente
durante la ejecucin del programa

Ejemplo: una grfica de una seal a la que se aade un nuevo valor recogido de un Slider a cada 0.1 s
y de forma que se desplaza hacia la izquierda cuando llega al extremo derecho

<Canvas x:Name="canvas" HorizontalAlignment="Left" Height="130" Margin="10,10,0,0"


VerticalAlignment="Top" Width="300" Background="#FF0D360B"/>

<Slider x:Name="entrada" HorizontalAlignment="Left" Margin="325,10,0,0"


VerticalAlignment="Top" Width="28" Maximum="100" Orientation="Vertical" Height="130"/>

System.Windows.Threading.DispatcherTimer temporizador;
// Objeto para implantar temporizaciones

int nPuntosEnCanvas = 0; // Nmero de puntos aadidos a la grfica


Polyline polilinea = new Polyline(); // Coleccin de puntos que se unen mediante lneas

private void Window_Loaded(object sender, RoutedEventArgs e) {


// Atiende al evento Loaded sobre la ventana de la aplicacin. Se produce al comienzo
// de la ejecucin del programa, una vez se han inicializado todos los recursos de la
// ventana

temporizador = new System.Windows.Threading.DispatcherTimer();


// Crea el objeto temporizador
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 70

temporizador.Tick += new EventHandler(temporizador_Tick);


// Indica que el evento que se produce al final de cada temporizacin se atiende
// mediante el mtodo temporizador_Tick

temporizador.Interval = new TimeSpan(0, 0, 0, 0, 100);


// Temporizaciones de 0.1 s.

temporizador.Start();
// Arranca el temporizador

polilinea.Stroke = Brushes.Yellow; // Color de dibujo


polilinea.StrokeThickness = 1; // Grosor de la polilnea
canvas.Children.Add(polilinea); // Aade la polilnea al canvas
}

private void temporizador_Tick(object sender, EventArgs e) {


// Atiende al evento que se produce al final de cada temporizacin, a cada 0.1 s
// Aade un nuevo punto a la grfica

if (nPuntosEnCanvas == canvas.Width) { // Si la grfica ocupa el ancho del canvas ...

polilinea.Points.RemoveAt(0); // Elimina el primer punto de la coleccin


Vector v = new Vector(-1, 0); // Vector de traslacin para decrementar en el eje X

// Recorriendo todos los puntos de la coleccin ...


for (int i = 0; i < polilinea.Points.Count; i++)
polilinea.Points[i] += v; // Traslada los puntos en el eje X hacia la izquierda

}
else nPuntosEnCanvas++; // Si no, indica que se va a aadir un nuevo punto

double escalaY = canvas.Height / (entrada.Maximum - entrada.Minimum);


polilinea.Points.Add(new Point(nPuntosEnCanvas, (entrada.Maximum-entrada.Value)*escalaY));
// Aade un nuevo punto a la derecha

35 Controles de usuario
El programador puede crear sus propios controles para
poder reutilizarlos varias veces en la misma aplicacin y en
aplicaciones diferentes

35.1 Controles de usuario a partir de otros controles

Para definir un nuevo control de usuario se pueden utilizar


uno o varios controles existentes

Se puede crear una biblioteca de controles, reutilizable para


utilizarla en otras aplicaciones

En un nuevo proyecto se desarrolla una biblioteca de


controles de usuario y una aplicacin que los utiliza
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 71

Ejemplo: control de usuario para visualizar el estado de un depsito

Consta de un control Image y de dos controles Rectangle

El control de tipo Image visualiza el contenido del archivo tanque.png,


que habr que copiar en el directorio donde estn los archivos de la
biblioteca y que habr que aadir al proyecto de la biblioteca

<UserControl

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BibliotecaControles" x:Class="BibliotecaControles.Deposito"
mc:Ignorable="d" Width="113" Height="268" SizeChanged="Deposito_SizeChanged">

<Grid >

<Image RenderOptions.BitmapScalingMode="HighQuality" Margin="0" Source="tanque.png"


Stretch="Fill" />
<Rectangle x:Name="rFondo" Fill="#FF686868" HorizontalAlignment="Left" Height="95"
Margin="19,14,0,0" VerticalAlignment="Top" Width="20"/>
<Rectangle x:Name="rProducto" Fill="Purple" HorizontalAlignment="Left" Height="117"
Margin="19,108,0,0" VerticalAlignment="Top" Width="20"/>

</Grid>

</UserControl>

En la imagen, con Margin="0" y Stretch="Fill" se logra que ocupe toda la superficie del control

El rectngulo rFondo es el rectngulo superior, en color gris, para representar el fondo del depsito

El rectngulo rProducto es el rectngulo coloreado en prpura, para representar la


cantidad de lquido almacenado

Se trata el evento SizeChanged para poder dimensionar y situar adecuadamente los


rectngulos rFondo y rProducto cuando se
redimensiona el control:

El cdigo se define en una clase derivada de


UserControl

Para el control de usuario, se pueden crear


propiedades que facilitarn su manejo en el diseador
de aplicaciones y en el cdigo

public partial class Deposito : UserControl {


// Clase para definir el comportamiento de los controles de tipo Deposito
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 72

// Datos necesarios para que cada depsito almacene su estado


double vMinimo = 0; // Cantidad mnima de producto
double vMaximo = 100; // Cantidad mxima de producto
double vPosicion = 50; // Cantidad de producto almacenado
Color vColorProducto; // Color con el que se muestra el producto almacenado
Brush brochaRelleno = Brushes.Purple; // Objeto para manejar el color del producto

public Deposito() { // Constructor


InitializeComponent(); // Inicializa los componentes internos
}

void redibujaDeposito() {
// Dibuja el depsito segn su estado actual

// Si an no se estableci el ancho o el alto de este control,


// entonces no dibuja nada
if (double.IsNaN(Width) || double.IsNaN(Height))
return;

double escalaX = (double)Width / 113;


double escalaY = (double)Height / 268;
// Obtiene factores de escala con respecto a las dimensiones iniciales del control

double posicionPuntos = (95 + 117) * vPosicion / (vMaximo - vMinimo) * escalaY;


// Obtiene la altura en puntos del rectngulo del producto

double fondoPuntos = (95 + 117) * (1 - vPosicion / (vMaximo - vMinimo)) * escalaY;


// Obtiene la altura en puntos del rectngulo del fondo

rFondo.Margin = new Thickness(19 * escalaX, 14 * escalaY, 0, 0);


// Posiciona el rectngulo del fondo

rFondo.Width = 20 * escalaX;
rFondo.Height = fondoPuntos;
// Establece las dimensiones del rectngulo del fondo

rProducto.Margin = new Thickness(19 * escalaX, 14 * escalaY + fondoPuntos, 0, 0);


rProducto.Width = 20 * escalaX;
rProducto.Height = posicionPuntos;
// Lo mismo para el rectngulo del producto

rProducto.Fill = brochaRelleno;
// Cubre de color el rectngulo del producto
}

public double Minimo { // Propiedad para manejar el valor mnimo


get { // Una lectura ...
return vMinimo; // ... devuelve una copia de este dato
}
set { // Una escritura ...
vMinimo = value; // ... modifica el dato
redibujaDeposito(); // y provoca que se redibuje el control
}
}

public double Maximo { // Propiedad para manejar el valor mximo


get {
return vMaximo;
}
set {
vMaximo = value;
redibujaDeposito();
}
}

public double Posicion { // Propiedad para manejar el valor actual


get {
return vPosicion;
}
set {
vPosicion = value;
redibujaDeposito();
}
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 73

// Propiedad para manejar el color con el que se visualiza el producto


public Color ColorProducto {
get {
return vColorProducto;
}
set {
vColorProducto = value;
brochaRelleno = new SolidColorBrush(vColorProducto);
redibujaDeposito();
}
}

private void Deposito_SizeChanged(object sender, SizeChangedEventArgs e) {


// Mtodo que atiende al evento SizeChanged, que se produce cuando se modifica el tamao
// del control

redibujaDeposito();
// Vuelve a dibujar el control con las nuevas dimensiones
}
}

En el diseo de una aplicacin que utiliza el control de


usuario, podemos personalizar el depsito utilizando las
propiedades definidas en el cdigo

35.2 Controles de usuario dibujados mediante cdigo

En el caso de no disponer de controles de partida adecuados, se puede dibujar el control de usuario


directamente en un Canvas mediante instrucciones de programa.

Ejemplo: una flecha de direccin que se puede rotar y que se puede mostrar intermitente

Solucin donde se crean dos proyectos:

- Proyecto BibliotecaControles de tipo WPF User Control Library donde se define el control
FlechaIntermitente.

- Proyecto Programa donde se define una aplicacin que utiliza ese control de usuario. En References
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 74

hay que incluir una referencia a BibliotecaControles.

FlechaIntermitente.xaml:

<UserControl x:Class="BibliotecaControles.FlechaIntermitente"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BibliotecaControles"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="50">
<Grid Loaded="Grid_Loaded" SizeChanged="Grid_SizeChanged">
<Canvas x:Name="canvas"/>
</Grid>
</UserControl>

FlechaIntermitente.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 75

namespace BibliotecaControles {

public partial class FlechaIntermitente : UserControl {

DispatcherTimer temporizador; // Para implantar la intermitencia


bool intermitente; // Cierto cuando la flecha tiene que parpadear
double angulo; // ngulo de rotacin en grados

public FlechaIntermitente() { // Constructor

InitializeComponent();

intermitente = false; // Inicialmente no parpadea


angulo = 0.0; // ngulo inicial

temporizador = new System.Windows.Threading.DispatcherTimer();


// Crea el objeto temporizador

temporizador.Tick += new EventHandler(temporizador_Tick);


// Indica que el evento que se produce al final de cada temporizacin se atiende
// mediante el mtodo temporizador_Tick

temporizador.Interval = new TimeSpan(0, 0, 0, 0, 300);


// La propiedad Interval del temporizador es un objeto de la clase TimeSpan donde
// se indica el intervalo de temporizacin en das, horas, minutos, segundos y
// milisegundos. En este caso las temporizaciones son de 0.3 s.
}

private void temporizador_Tick(object sender, EventArgs e) {


// Atiende al evento que se produce al final de cada temporizacin

if (intermitente) { // Si tiene que parpadear ...

if (canvas.Visibility == Visibility.Visible) // Cambia la visibilidad del canvas


canvas.Visibility = Visibility.Hidden;
else canvas.Visibility = Visibility.Visible;
}
}

public bool Intermitente { // Propiedad pblica para controlar la intermitencia

get {
return intermitente; // Devuelve una copia de la variable
}

set {
intermitente = value; // Actualiza la variable

if (intermitente) // Si hay intermitencia ...


temporizador.Start(); // Arranca el temporizador
else {
temporizador.Stop(); // si no, lo para
canvas.Visibility = Visibility.Visible; // En cualquier caso, muestra el canvas
}
}
}

public double Angulo { // Propiedad pblica para manejar el ngulo de rotacin

get {
return angulo; // Devuelve una copia de la variable
}

set {
angulo = value; // Actualiza la variable
dibujaFlecha(); // Redibuja la flecha con el nuevo ngulo
}
}

Point rotaPunto(Point punto, Point origen, double anguloGrados) {


// Devuelve un punto resultado de la rotacin de un punto con respecto a un origen

double anguloRadianes = anguloGrados * (Math.PI / 180); // Conversin grados a radianes


Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 76

double coseno = Math.Cos(anguloRadianes);


double seno = Math.Sin(anguloRadianes);

return new Point (


(int) (coseno * (punto.X - origen.X) - seno * (punto.Y - origen.Y) + origen.X),
(int) (seno * (punto.X - origen.X) + coseno * (punto.Y - origen.Y) + origen.Y)
);
}

private void dibujaFlecha() {


// Dibuja la flecha segn las dimensiones del canvas y segn el ngulo de rotacin

Polygon flecha = new Polygon(); // Polgono definido por sus vrtices

flecha.Stroke = Brushes.Black; // Color de borde


flecha.Fill = Brushes.LightGreen; // Color de fondo
flecha.StrokeThickness = 1; // Grueso del borde

flecha.HorizontalAlignment = HorizontalAlignment.Center;
flecha.VerticalAlignment = VerticalAlignment.Center;
// La flecha se sita en el centro del canvas

flecha.Points = new PointCollection();


// Contiene una coleccin de puntos para definir sus vrtices

Point centro = new Point(Width / 2, Height / 2);


// El centro del canvas es el origen utilizado para realizar las rotaciones

flecha.Points.Add(rotaPunto(new Point(Width / 2, 0), centro, angulo));


flecha.Points.Add(rotaPunto(new Point(Width, Height / 3), centro, angulo));
flecha.Points.Add(rotaPunto(new Point(Width * 3 / 4, Height / 3), centro, angulo));
flecha.Points.Add(rotaPunto(new Point(Width * 3 / 4, Height), centro, angulo));
flecha.Points.Add(rotaPunto(new Point(Width / 4, Height), centro, angulo));
flecha.Points.Add(rotaPunto(new Point(Width / 4, Height / 3), centro, angulo));
flecha.Points.Add(rotaPunto(new Point(0, Height / 3), centro, angulo));
// Aade todos los vrtices rotados con respecto al centro del canvas

canvas.Children.Clear(); // Elimina una posible flecha existente


canvas.Children.Add(flecha); // Aade la nueva flecha
}

private void Grid_Loaded(object sender, RoutedEventArgs e) {


// Al comienzo del programa, cuando se crea el Grid
dibujaFlecha();
}

private void Grid_SizeChanged(object sender, SizeChangedEventArgs e) {


dibujaFlecha();
}

} // Fin de la clase FlechaIntermitente


} // Fin del espacio de nombres BibliotecaControles

MainWindow.xaml:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Programa"
xmlns:BibliotecaControles="clr-namespace:BibliotecaControles;assembly=WpfControlLibrary1"
x:Class="Programa.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="249" Width="403">

<Grid>
<Slider x:Name="slider" HorizontalAlignment="Left" Margin="246,108,0,0"
VerticalAlignment="Top" Width="123" LargeChange="0" Maximum="360"
ValueChanged="slider_ValueChanged"/>
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 77

<CheckBox x:Name="checkIntermitencia" Content="Intermitencia"


HorizontalAlignment="Left" Margin="246,57,0,0" VerticalAlignment="Top"
Click="checkIntermitencia_Click"/>
<BibliotecaControles:FlechaIntermitente x:Name="flecha" HorizontalAlignment="Left"
Height="143" Margin="69,30,0,0" VerticalAlignment="Top" Width="65"/>
<Label x:Name="labelAngulo" Content="ngulo = 0" HorizontalAlignment="Left"
Margin="269,125,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Programa {

public partial class MainWindow : Window {

public MainWindow() { // Construtor de la ventana


InitializeComponent(); // Inicializa todos los controles
}

private void slider_ValueChanged(object sender,


RoutedPropertyChangedEventArgs<double> e) {
// Atiende al evento que se produce cuando el usuario mueve el slider

flecha.Angulo = slider.Value;
// El ngulo de rotacin de la flecha lo fija el valor del slider

labelAngulo.Content = String.Format("ngulo = {0:N1}", slider.Value);


// Muestra el ngulo en la etiqueta, con un decimal
}

private void checkIntermitencia_Click(object sender, RoutedEventArgs e) {


// Atiende al evento que se produce cuando el usuario hace click sobre el checkbox

flecha.Intermitente = (bool) checkIntermitencia.IsChecked;


// Activa o desactiva la intermitencia de la flecha segn el estado del checkbox
}
}
}
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 78

36 Interfaces flexibles
En muchos tipos de situaciones el
programa tiene que utilizar un
nmero variable de controles en
funcin de ciertos datos

Mediante instrucciones podemos


crear objetos para manejar
controles de cualquier tipo

Estos controles se pueden aadir


a las colecciones de objetos
utilizadas por los contenedores
como Grid, StackPanel, etc.

Ejemplo: un programa que puede


manejar un nmero variable de
depsitos

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Programa"
xmlns:BibliotecaControles="clr-namespace:BibliotecaControles;assembly=BibliotecaControles"
x:Class="Programa.MainWindow" mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">

<Grid>
<TextBox x:Name="editorNDatos" HorizontalAlignment="Left" Height="23"
Margin="293,22,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="49"/>
<Button x:Name="botonNDatos" Content="OK" HorizontalAlignment="Left"
Margin="362,24,0,0" VerticalAlignment="Top" Width="48" Click="botonNDatos_Click"/>
<Label x:Name="label" Content="Num. depsitos" HorizontalAlignment="Left"
Margin="196,21,0,0" VerticalAlignment="Top"/>
<StackPanel Orientation="Horizontal" x:Name="panel" Margin="0,60,0,0" />
</Grid>

</Window>

private void botonNDatos_Click(object sender, RoutedEventArgs e) {


// Cuando se introduce el nmero de datos ...

panel.Children.Clear();
// Borra toda la coleccin de controles existentes en el panel

int nDepositos = Convert.ToInt32(editorNDatos.Text);


// Determina el nmero de depsitos

for (int i = 1; i <= nDepositos; i++) { // Para cada Depsito ...

Deposito d = new Deposito(); // Crea un control depsito


d.Minimo = 0; // Establece valor mnimo
d.Maximo = 100; // y el mximo
d.Height = 200; // Establece el ancho
d.Width = 100; // y el alto
d.Margin = new Thickness(10); // Establece un margen de 10 puntos alrededor
panel.Children.Add(d); // Lo aade al panel

Slider s = new Slider(); // Crea un control Slider


s.Orientation = Orientation.Vertical; // que va a funcionar en vertical
s.Minimum = 0; // Establece el valor mnimo
s.Maximum = 100; // y el mximo
Desarrollo OOP - Informtica Industrial 2017/2018 - Escuela de Ingeniera Industrial - Universidad de Vigo 79

s.Height = 200; // Establece el alto


s.Width = 20; // y el ancho
s.Margin = new Thickness(0, 10, 10, 20); // 10px arriba y abajo, 20px a la derecha

s.ValueChanged += new RoutedPropertyChangedEventHandler<double>(slider_ValueChanged);


// Hace que el evento ValueChanged se trate con el mtodo slider_ValueChanged

panel.Children.Add(s); // Aade el slider al panel

}
}

private void slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {


// Se ejecuta cuando se mueve cualquier slider

Slider sliderCausante = (Slider)sender; // Referencia al objeto que produjo el evento

int nDeposito = panel.Children.IndexOf(sliderCausante) / 2;


// Lo busca en la coleccin de componentes del panel y determina el nmero de depsito
// 0,1,2,...

Deposito deposito = (Deposito) panel.Children[nDeposito * 2];


// Obtiene una referencia al componente depsito correspondiente

deposito.Posicion = sliderCausante.Value; // Modifica la posicin del depsito


}

También podría gustarte