Introducción al desarrollo de aplcaciones con WPF (Windows Presentation Foundation), la cual utiliza la tecnología XAML (eXtensible Application Markup Language), haciendo uso simple del patrón de diseño orientado a plataformas XAML y consumo de datos de una api publica. Aplicación de ejemplo desarrollada dentro de la presentación.
2. Es un framework de nueva generación que cuenta
con la integración de varios frameworks como GDI
(Graphic Device Interface) y GDI+, influenciado
fuertemente por kits de herramientas para Web,
como lo son Adobe Flash
Podemos crear aplicaciones con experiencia de
usuario visualmente satisfactoria
3. WPF existe como una gran parte del framework de
.NET que están ubicados en su mayor parte en el
espacio de nombres de System.Windows
Si se cuenta con experiencia en ASP.NET o Windows
Forms, la programación con WPF te sonará familiar;
se instancian clases, asignas propiedades, mandas
a llamar métodos y manejar eventos, todo por
medio de tu lenguaje de programación favorito: C#
o VB
4. Podemos crear una separación entre la lógica y la
apariencia de nuestra aplicación, obteniendo los
siguientes beneficios:
Costos de desarrollo y mantenimiento son
reducidos, ya que la apariencia no esta fuertemente
ligada con el comportamiento de la aplicación.
5. El desarrollo es mas eficiente, ya que los
diseñadores pueden estar trabajando en la
apariencia de la aplicación mientras
desarrolladores trabajan en el comportamiento.
Podemos usar múltiples herramientas de diseño
para nuestras aplicaciones como Microsoft
Expression.
Globalizacion y localización para aplicaciones con
WPF se ha simplificado (Globalización y
Localización con WPF)
6. Es un lenguaje de marcado basado en XML para
implementar la apariencia de una aplicación
declarativamente.
Se usa para crear ventanas, diálogos, páginas,
controles de usuario, dibujos y/o gráficas.
Se usa para el diseño de vistas para Workflow
markup, Windows Phone 7 y 8, Aplicaciones para
Windows Store, y mas !
7. Mismas reglas que en XML
o Debe de existir un nodo raíz
o Todo elemento debe de cerrar
o Sensible a mayúsculas y minúsculas
o Existen elementos y subelementos
o Existen atributos para cada elemento
8. Los elementos instancian un objeto
<Rectangle />
Los atributos cambian las características de los
objetos
<Rectangle Width=“100” Height=“100” />
El anidamiento implica pertenencia
<Grid>
<Rectangle />
</Grid>
9. A todo elemento declarado en XAML, le debe de
corresponder a una clase dentro del espacio de
nombres de la API de .NET
◦ Por ejemplo
Elemento XAML Clase
<Rectangle /> System.Windows.Shapes.Rectangle
<Button /> System.Windows.Controls.Button
<ListBox /> System.Windows.Controls.ListBox
10. Se usan para organizar lógicamente las clases
http://schemas.microsoft.com/winfx/2006/xaml
/presentation
◦ Espacio de nombres base. Abarca todos los
espacios de nombres CLR (Common Language
Runtime)
http://schemas.microsoft.com/winfx/2006/xaml
Espacio de nombres de XAML
11. El atributo xmlns importa un espacio de nombres
XML para dejar a nuestro alcance todos los
miembros incluidos en el
Es similar a una sentencia using en C# o Imports en
VB
Podemos asignar de manera opcional un alias a
nuestros espacios de nombres (xmlns:alias)
12. Se puede establecer el atributo xmlns en cualquier
nivel de nuestra aplicación
Lo mas conveniente es colocar el espacio de
nombres en la raíz de la página o ya sea de la
aplicación
<Grid
xmlns:ans=http://schemas.microsoft.com/winfx/2006/x
aml/presentation>
<ans:Button Width=“200” Height=“100” Content=“Click
me!” />
</Grid>
13. Todas las propiedades se pueden establecer como
subelementos dentro de un documento XAML
Es necesario únicamente cuando el valor de una
propiedad es un objeto complejo y no se cuenta
con un convertidor de tipo
<Rectangle Width=“100” Height=“100” Fill=“Yellow” />
es lo mismo que:
<Rectangle>
<Rectangle.Width>100</Rectangle.Width>
<Rectangle.Height>100</Rectangle.Height>
<Rectangle.Fill>Yellow</Rectangle.Fill>
</Rectangle>
14. Son clases que permiten al intérprete de XAML el
evaluar de distintas maneras sus valores
◦ {StaticResource}
◦ {Binding}
◦ {TemplateBinding}
◦ {RelativeSource}
◦ {x:Null}
Sintáxis:
<Element property=“{Extensión [Properties]}” />
15. Se refieren a una bolsa de propiedades
La clase FrameworkElement implementa la
propiedad Resources
◦ Permite guardar cualquier tipo de objeto para
reutilizarlo
◦ Se identifican por medio de una cláve única
(atributo x:Key)
<Grid.Resources>
<SolidColorBrush x:Key=“myBrush”
Color=“Red” />
</Grid.Resources>
16. Se referencían en XAML por medio de la extensión
{StaticResource}
{StaticResource} puede ser usada en propiedades
regulares CLR
<Window.Resources>
<SolidColorBrush x:Key=“myBrush”
Color=“Red” />
</Window.Resources>
<Rectangle Width=“100” Height=“100”
Fill=“{StaticResource myBrush}” />
17. Recursos via código
◦ Dentro del código de la aplicación usamos la
propiedad Resources para leer o agregar objetos al
diccionario de recursos
◦ La propiedad Resources es un diccionario del tipo
<object,object>
Private void Button_Click(object sender, RoutedEventArgs e)
{
if(this.Resources.Contains(“myBrush”)
// obtenemos el recurso
var brush = this.Resources[“myBrush”] as
SolidColorBrush;
//agregamos un recurso
this.Resources.Add(“resource”, resourceObject);
}
18. Tipo especial de propiedad dependiente
Notifican al elemento padre que se requiere cierto
valor
Sintáxis XAML
<ParentClass>
<Element ParentClass.Property = “Value” />
</ParentClass>
19. Se pueden utilizar los métodos SetValue() y
GetValue() como en cualquier otra propiedad
dependiente
if ((double) rect.GetValue(Grid.Column) == 1)
{
rect.SetValue(Grid.Column, 2);
}
Se pueden usar los métodos para leer o establecer
los valores de las propiedades adjuntas
if (Grid.GetColumn(rect) == 1)
{
Grid.SetColumn(rect, 2);
}
20. Contenedores visuales
Clases que heredan de la clase base Panel
◦ Canvas
◦ StackPanel
◦ Grid
Otros
◦ Border
◦ ScrollViewer
21. Contenedor básico de posicionamiento
absoluto
Propiedades adjuntas
◦ Left
◦ Right
◦ Top
◦ Bottom
24. Contenedor para apilar elementos de manera
horizontal o vertical
Útil en escenarios donde necesites alinear
controles
◦ Casos como un menú, una barra de botones, etc
25. Véase el siguiente fragmento de código:
<StackPanel>
<Rectangle Width=”150” Height=“150”
Fill=“Blue” />
<Rectangle Width=”150” Height=“150”
Fill=“Orange”/>
</StackPanel>
26.
27. Contenedor de tipo tabla
Es el más flexible de todos los contenedores
Permite definir columnas y filas
Propiedades adjuntas:
◦ Column
◦ Row
◦ ColumnSpan
◦ RowSpan
28. Los altos y anchos de filas y columnas
pueden ser de 3 tipos:
◦ Fijo
Se mide en pixeles
◦ Automático
En función de su contenido
◦ Proporcional(*)
Predeterminado
34. System.Windows.Controls
Clase para representar una imagen
Similar al elemento <img> de HTML
Puede tener una fuente absoluta o relativa
Soporta solo imágenes png y jpg
<Image Source=“someImg.png”/>
<Image
Source=“http://www.somepage.com/someImg.jpg” />
35. System.Windows.Controls
Elemento principal para mostrar texto en las
aplicaciones XAML
Soporta cambiar el tamaño de la fuente, el
tipo, las decoraciones, alineaciones, etc
Run
◦ Permite estilizar partes del texto de un TextBlock
LineBreak
◦ Salto de línea explícito
36. Véase el siguiente fragmento de código
<TextBlock FontSize="50"
TextWrapping="Wrap">
<Run
Foreground="Blue">Taller</Run>
de desarrollo de aplicaciones
<LineBreak />
con
<Run
Foreground="Gold">WPF</Run>
<LineBreak />
<Run Foreground="Red">Semana ISW</Run>
</TextBlock>
37.
38.
39.
40. Modelo robusto
◦ Objeto fuente
Propiedad en el objeto fuente
◦ Control destino
Propiedad en el control destino
Se expresan a través de la extensión del
Markup {Binding}
<TextBlock Text=“{Binding Source={StaticResource User},
Path=UserName}” />
41. Parámetros principales de {Binding}
◦ Source
Indica el objeto fuente
◦ Path
Indica una ruta a la propiedad en el objeto fuente
Parámetro predeterminado
◦ Mode
Indica el modo para el enlace
42. OneTime
◦ El enlace se establece y el objeto fuente y el control
destino no se vuelven a comunicar entre sí
OneWay
◦ El enlace se establece y cuaquier cambio que
suceda en el objeto fuente le avisará al control
destino
TwoWay
◦ El enlace se establece y cuaquier cambio que
suceda en el objeto fuente le avisará al control
destino y viceversa (bi-direccional)
43. Se expresan a través del atributo Mode
<TextBlock
Text=“{Binding
Source={StaticResource User},
Path=UserName,
Mode=TwoWay}” />
44. Los modos OneWay y TwoWay requieren que
el objeto fuente implemente alguna de las
interfaces INotifyPropertyChanged o
INotifyCollectionChanged
◦ Implementan un evento, el cual es escuchado en la
infraestructura de enlace de datos
◦ INotifyPropertyChanged en objetos individuales,
para notifucar que una propiedad ha cambiado
◦ INotifyCollectionChanged en colecciones, para
notificar que una colección ha cambiado
45. Windows Presentation Foundation soporta el
atributo CallerMemberName
◦ Obtiene automáticamente el nombre del método o
propiedad que mandó a llamar al método en
cuestión
◦ Se evita el uso de “cadenas mágicas”, lo cual no
dificulta el dar mantenimiento a las aplicaciones
◦ Disponible en System.Runtime.CompilerServices
46. Clase base que implementa
INotifyPropertyChanged
protected virtual void OnPropertyChanged([CallerMemberName]
string propertyName = null)
{
If(PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs(propertyName));
}
}
47. Colección genérica recomendada para
escenarios de enlace de datos
Implementa INotifyPropertyChanged y
INotifyCollectionChanged
Automáticamente actualiza el control de lista
que esté enlazada
Disponible en
System.Collections.ObjectModel
ObservableCollection<User> …
48. Expresan el XAML que representa a cada uno
de los elementos en un control, lo podemos
usar en listas, botones, etc
Se expresan con el elemento DataTemplate o
ControlTemplate
Se declaran en linea junto con el elemento a
personalizar, o dentro del diccionario de
recursos de la pagina o aplicación
50. Clases que implementan la interfaz
IValueConverter
La interfaz IValueConverter incluye dos
métodos a implementar:
◦ Convert
Método que se ejecuta cuando el valor fluye del objeto
fuente hacia el control destino
◦ ConvertBack
Método que se ejecuta cuando el valor fluye de
regreso: del control destino hacia el objeto fuente
51. Son “funcionalidad enlazable”
Clases que implementan la interfaz
ICommand
Soportados por la familia de clases
ButtonBase
Miembros:
◦ Execute: Indica qué acción se realizará
◦ CanExecute: Determina si el comando puede
ejecutar
◦ CanExecuteChanged: Re-evalúa CanExecute
52.
53. Patrón de diseño natural para plataformas
XAML
◦ Aprovecha al máximo el enlace de datos {Binding}
Ventajas
◦ Separacion de concerns (preocupaciones)
◦ Pruebas unitarias
◦ Mantenimiento de código
◦ Consistencia
◦ Desacoplamiento
◦ Flujo de trabajo entre diseñadores y desarrolladores
◦ Reutilización de código
◦ ..y muchos beneficios mas..
54. View
100% Declarative via XAML
ViewModel
Exposes Model to View for data binding
Exposes logic to user via data bound ICommands
Application-specific state and logic
Model
Domain specific entities and operations
Contains no knowledge of specific usage
Data binding of
commands
Data binding
of properties
Direct access via
code
55. View
◦ Define la interfaz de usuario
◦ Define la estructura y apariencia de lo que el
usuario ve en la pantalla
◦ Estilos, recursos
◦ El contexto de datos es el ViewModel
◦ Poco o nada de code-behind
Solo código que no necesite pruebas unitarias
◦ Comportamientos
◦ Actualizada a través de Bindings
56. ViewModel
◦ Es una abstracción de la Vista
◦ Implementa la lógica de presentación
◦ Adapta el modelo a la vista
◦ Mantiene el estado
◦ Expone propiedades a las que se enlaza la vista
(datos y comandos)
◦ Expone metodos que los comportamientos de una
vista puede invocar
◦ Desacoplamiento y Testability es el objetivo
principal del ViewModel
57. Model
◦ Tu dominio
◦ Objetos de datos
DTO, POCO
Modelo de datos generado
Modelo de proxy generado
◦ Capa de servicios
Repositorios
Objetos negocio
58. Cardinalidad
◦ Generalmente, una vista solo tiene un ViewModel
◦ Un ViewModel puede ser usado en una o más vistas
◦ Un Model puede ser usado en uno o mas
ViewModels
59. Estrategias para relacionar View con
ViewModel
◦ Primero la vista (View first)
La vista creal el ViewModel (en XAML o code-behind)
La vista tiene inyectado el ViewModel (propiedad o
constructor)
◦ Primero el ViewModel (ViewModel first)
El ViewModel crea la vista, se enlaza a sí mismo a la
vista
60. Para cambiar una vista, siempres se debe de
implementar una propiedad en el ViewModel
◦ Para deshabilitar un boton: enlaza una propiedad
◦ Para cambiar el estado de la vista: enlaza una propiedad
◦ Para iniciar alguna animación: enlaza una propiedad
◦ Para mostrar errores de validación: enlaza una
propiedad
Para que la vista ejecute código
◦ Los controles de la vista se enlazan a propiedades de
tipo ICommand
◦ Los comportamientos de la vista pueden invocar
métodos o enlazar un evento a un comando
62. Si recapitulamos
◦ La vista es XAML
◦ La vista puede tener code-behind
Solo el código relacionado con la UI
◦ La vista mantiene una referencia al ViewModel
◦ La vista se enlaza al ViewModel
◦ La vista utiliza comandos para invocar métodos en
el ViewModel
◦ La vista utiliza comportamientos para invocar
metodos en el ViewModel
◦ El ViewModel mantiene una referencia al Model
63. Crea un proyecto nuevo de Visual Studio
2012
64. Dale el nombre WorkshopApp
Observa la arquitectura de tu proyecto
65. Agrega 3 folders con los nombres Models,
ViewModels y Views, la vista llamada
MainWindow arrástrala al folder Views
Ahora abre tu documento
App.xaml
66. Cambia el StartupUri de la aplicación al de la
vista que está en el folder Views
67. Da click derecho sobre el proyecto y
selecciona la opción Manage NuGet Packages
◦ Busca el paquete llamado HttpClient e instálalo,
aceptando los términos y condiciones
68. Model
◦ Crea una clase pública llamada New con las
siguientes propiedades
69. Model
◦ Crea una clase pública llamada NewsEventArgs que
herede de la clase base EventArgs.
◦ Este evento debe de guardar una lista de noticias,
resultado de un consumo de datos de una API de
noticias
70. Model
◦ Crea una clase llamada NewsService y agrega un
manejador de eventos para NewsEventArgs
◦ Agrega una constante llamada NewsUriFormat con
la siguiente cadena
“http://apiservice.univision.com/rest/feed/getFeed?url=%2Fsearch%2Fa
rticles%3Fcount%3D{1}%26site%3Dnoticias%26tags%3D{0}%26outputMode%3D
xml&api_key={2}”
71. Model
◦ Crea una funcion llamada GetNews que reciba una cadena como
parámetro.
◦ Usaremos la clase XDocument para procesar la respuesta en formato XML
por medio de un query
72. ViewModel
◦ Crea una clase llamada ActionCommand que
implemente las funciones de ICommand.
◦ Crea una propiedad a nivel de clase del tipo Action
y que sea recibida por medio del constructor.
◦ La función CanExecute devolverá un valor verdadero
◦ La función Execute debera ejecutar la acción
definida como propiedad
73. ViewModel
◦ Crea una clase pública llamada BaseViewModel que
implemente la interface INotifyPropertyChanged,
ésta clase sera la base para todos los ViewModels,
recuerda usar el atributo CallerMemberName
74. ViewModel
◦ Ahora crea una clase pública llamada NewsViewModel, ésta debe de
heredar de la clase base BaseViewModel
◦ Encapsula las propiedades que desees enlazar a la vista de la aplicación
(en este caso crearás una propiedad llamada city y en el accesor set llama
a la función OnPropertyChanged para notificar el cambio)
◦ Sigue el mismo procedimiento con
con una propiedad del tipo
ObservableCollection<New>
75. ViewModel
◦ Crea una propiedad privada de la clase
NewsService, e inicializala dentro del constructor
del ViewModel junto con el manejador del evento
GetNewsCompleted
76. ViewModel
◦ Crea una propiedad de la clase ActionCommand y encapsúlala, se debe de
crear una clase por cada comando deseado dentro de la vista
◦ Dentro del accesor get, checa que si el campo no es nulo, de ser así, crea
una nueva instancia del campo getNewsCommand, asignandole una acción
por medio de una expresión lambda
◦ Dentro del cuerpo de la acción, manda
a llamar la funcion GetNews,
que pertenece a la propiedad
del tipo NewsService
77. View
◦ Importemos el espacio de nombres de ViewModels
a la ventana XAML
◦ Creemos una instancia de NewsViewModel dentro
del diccionario de recursos de la ventana
78. View
◦ Dividimos en dos filas nuestro Grid principal, y le
asigamos a la propiedad DataContext el ViewModel
alojado en el diccionario de recursos
79. View
◦ A la primera fila le agregamos una caja de búsqueda y un botón para
iniciar una búsqueda de noticias, enlazandolo a nuestro comando de
noticas; podemos usar algún DataTemplate para darle estilo a nuestro
botón
80. View
◦ A la segunda fila le agregamos un elemento
ListBox, el cual estará enlazado a nuestra lista de
noticias en el ViewModel, creando un ItemTemplate
para cada elemento en el ListBox
Notas del editor
Anidamiento se refiere a la ley de elementossubyacentes