Académique Documents
Professionnel Documents
Culture Documents
INDICE GENERAL
1. Introduccin a WPF
1.1. Introduccin a Windows Presentation Foundation
1.2. Informacin General sobre Windows Presentation Foundation
1.3. Lo Nuevo en Windows Presentation Foundation Versin 3.5
2. Desarrollo de Aplicaciones
2.1. Informacin General sobre el Desarrollo de Aplicaciones
2.2. Administracin de Aplicaciones
2.2.1. Informacin General sobre la Administracin de Aplicaciones
2.2.2. Archivos c Windows Presentation Foundation
2.2.3. URIs de Paquete en Windows Presentation Foundation
2.2.4. Temas Cmo del Modelo de Aplicaciones
2.2.4.1. Cmo: Obtener y Establecer Propiedades en el Ambito de Aplicacin
2.2.4.2. Cmo: Obtener y Establecer Recursos en el Ambito de Aplicacin
2.2.4.3. Cmo: Obtener y Establecer el Cdigo de Salida de Aplicaciones
2.2.4.4. Cmo: Obtener los Argumentos de Lnea de Comandos
2.2.4.5. Cmo: Obtener el Objeto de Aplicacin Actual
2.2.4.6. Cmo: Conservar y Restaurar Propiedades en el Ambito de
Aplicacin a travs de Sesiones de Aplicacin
2.2.4.7. Cmo: Cerrar una Aplicacin
2.2.4.8. Cmo: Iniciar una Aplicacin
2.2.4.9. Cmo: Usar un Diccionario de Recursos en el Ambito de Aplicacin
2.3. Ventanas en Aplicaciones de Windows Presentation Foundation
2.3.1. Informacin General sobre Ventanas de WPF
2.3.2. Informacin General sobre Cuadros de Dilogo
2.3.3. Temas Cmo de la Administracin de Ventanas
2.3.3.1. Cmo: Cambiar Automticamente el Tamao de una Ventana para
que se Ajuste a su Contenido
2.3.3.2. Cmo: Obtener Todas las Ventanas de una Aplicacin
2.3.3.3. Cmo: Obtener y Establecer la Ventana Principal de una Aplicacin
2.3.3.4. Cmo: Abrir un Cuadro de Dilogo
2.3.3.5. Cmo: Abrir un Cuadro de Mensaje
2.3.3.6. Cmo: Abrir una Ventana
2.3.3.7. Cmo: Devolver el Resultado de un Cuadro de Dilogo
2.4. Navegacin en Aplicaciones de Windows Presentation Foundation
2.4.1. Informacin General sobre Navegacin
2.4.2. Informacin General sobre la Navegacin Estructurada
2.4.3. Informacin General sobre Topologas de Navegacin
2.4.4. Temas Cmo de Navegacin
2.4.4.1. Cmo: Llamar a una Funcin de Pgina
2.4.4.2. Cmo: Determinar si una Pgina est Hospedada en un Explorador
2.4.4.3. Cmo: Obtener el Valor Devuelto por una Funcin de Pgina
2.4.4.4. Cmo: Navegar hacia Delante por el Historial de Navegacin
2.4.4.5. Cmo: Navegar hacia Atrs por el Historial de Navegacin
2.4.4.6. Cmo: Navegar hasta una Pgina
2.4.4.7. Cmo: Actualizar una Pgina
2.4.4.8. Cmo: Devolver Resultados de una Funcin de Pgina
2.4.4.9. Cmo: Establecer el Alto de una Ventana desde una Pgina
2.4.4.10. Cmo: Establecer el Ancho de una Ventana desde una Pgina
2.4.4.11. Cmo: Establecer el Ttulo de una Ventana desde una Pgina
2.4.4.12. Cmo: Detener la Carga de una Pgina
2.4.4.13. Cmo: Usar Mailto: para Enviar Correo desde una Pgina
2.5. Extensibilidad de Aplicaciones
2.5.1. Informacin General sobre Complementos de WPF
2.5.2. Temas Cmo de Complementos de WPF
2.5.2.1. Cmo: Crear un Complemento que Devuelva una Interfaz de Usuario
2.5.2.2. Cmo: Crear un Complemento que sea una Interfaz de Usuario
2.6. Hospedar Aplicaciones de Windows Presentation Foundation
2.6.1. Informacin General sobre Aplicaciones de Explorador XAML de WPF
Pag 1 de 445
Pag 2 de 445
Pag 3 de 445
Pag 4 de 445
Pag 5 de 445
1. Introduccin a WPF
Este portal proporciona vnculos a informacin destinada a programadores que son nuevos en Windows
Presentation Foundation (WPF).
La plataforma de desarrollo WPF se ha generado sobre un sistema de programacin bsico, que se extiende
para admitir un amplio conjunto de caractersticas de desarrollo de aplicaciones que incluyen el propio modelo
de aplicacin, recursos, controles, grficos, diseo, enlace de datos, documentos y seguridad.
Pag 6 de 445
Se pueden utilizar varias herramientas de diseo para implementar y compartir el lenguaje marcado
XAML, a fin de responder a los requisitos de los colaboradores de programacin de aplicaciones;
Microsoft Expression Blend proporciona una experiencia apropiada para los diseadores, mientras que
Visual Studio 2005 est dirigido a los programadores.
A continuacin, se muestra una introduccin breve al cdigo de lenguaje marcado y subyacente de WPF.
Marcado
XAML es un lenguaje de marcado basado en XML que se utiliza para implementar la apariencia de una
aplicacin mediante declaracin. Se suele utilizar para crear ventanas, cuadros de dilogo, pginas y controles
de usuario, as como para rellenarlos con controles, formas y grficos.
En el ejemplo siguiente se utiliza XAML para implementar la apariencia de una ventana que contiene un solo
botn.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Window with Button"
Width="250" Height="100">
<!-- Add button to window -->
<Button Name="button">Click Me!</Button>
</Window>
En concreto, este cdigo XAML define una ventana y un botn mediante los elementos Window y Button,
respectivamente. Cada elemento se configura con atributos, como el atributo Title del elemento Window, para
especificar el texto de la barra de ttulo de la ventana. En tiempo de ejecucin, WPF convierte los elementos y
los atributos definidos en el marcado en instancias de clases de WPF. Por ejemplo, el elemento Window se
convierte en una instancia de la clase Window cuya propiedad Title es el valor del atributo Title.
En la ilustracin siguiente se muestra la interfaz de usuario (UI) definida mediante el cdigo XAML del ejemplo
anterior.
Puesto que XAML se basa en XML, la interfaz de usuario que se crea con este lenguaje se ensambla en una
jerarqua de elementos anidados que se denomina rbol de elementos. El rbol de elementos proporciona una
manera lgica e intuitiva de crear y administrar las UIs.
Pag 7 de 445
Aplicaciones
.NET Framework, System.Windows, as como el cdigo de lenguaje marcado y subyacente, constituyen la base
de la experiencia de programacin de aplicaciones en WPF. Adems, WPF cuenta con caractersticas completas
para crear experiencias de usuario con contenido enriquecido. Para empaquetar este contenido y distribuirlo a
los usuarios en forma de "aplicaciones", WPF proporciona tipos y servicios denominados colectivamente el
modelo de aplicacin. El modelo de aplicacin admite la programacin de aplicaciones independientes y
hospedadas en explorador.
Aplicaciones independientes
Pag 8 de 445
Adems, puede utilizar los cuadros de dilogo siguientes de WPF: MessageBox, OpenFileDialog, SaveFileDialog
y PrintDialog.
Aplicaciones hospedadas en explorador
Para las aplicaciones hospedadas en explorador, denominadas Aplicaciones del explorador XAML (XBAPs),
puede crear pginas (Page) y funciones de pgina (PageFunction<(Of <(T>)>)) entre las que se puede navegar
mediante hipervnculos (clases Hyperlink). En la ilustracin siguiente se muestra una pgina de XBAP
hospedada en Internet Explorer 7.
Las aplicaciones WPF se pueden hospedar en Microsoft Internet Explorer 6 y Internet Explorer 7. WPF
proporciona las dos opciones siguientes de hosts de navegacin alternativos:
Clase Application
Tanto las XBAPs como las aplicaciones independientes suelen ser bastante complejas y necesitan servicios
adicionales de mbito de la aplicacin, lo que incluye administracin del inicio y de la duracin, as como
propiedades y recursos compartidos. La clase Application encapsula todos estos servicios y algunos ms, y slo
se puede implementar mediante XAML, como se muestra en el ejemplo siguiente.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />
Pag 9 de 445
Pag 10 de 445
WrapPanel: los controles secundarios se sitan por orden de izquierda a derecha y se ajustan a la lnea
siguiente cuando hay ms controles de los que caben en la lnea actual.
En el ejemplo siguiente se utiliza un control DockPanel para situar varios controles TextBox.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.LayoutWindow"
Title="Layout with the DockPanel" Height="143" Width="319">
<!--DockPanel to layout four text boxes-->
<DockPanel>
<TextBox DockPanel.Dock="Top">Dock = "Top"</TextBox>
<TextBox DockPanel.Dock="Bottom">Dock = "Bottom"</TextBox>
<TextBox DockPanel.Dock="Left">Dock = "Left"</TextBox>
<TextBox Background="White">This TextBox "fills" the remaining
space.</TextBox>
</DockPanel>
</Window>
DockPanel permite que los controles secundarios TextBox le indiquen cmo se deben organizar. Para ello,
DockPanel implementa una propiedad Dock que se expone a los controles secundarios, a fin de para permitir
que cada uno de ellos especifique un estilo de acoplamiento.
Nota:
Una propiedad implementada por un control principal para que la utilicen los controles secundarios es una
construccin de WPF denominada propiedad asociada.
En la ilustracin siguiente se muestra el resultado del marcado XAML del ejemplo anterior.
Enlace de datos
La mayora de las aplicaciones se crean para proporcionar recursos a los usuarios que les permitan ver y editar
los datos. Para aplicaciones WPF, el trabajo de almacenar los datos y tener acceso a ellos se proporciona
mediante tecnologas existentes, como Microsoft SQL Server y ADO.NET. Despus de obtener acceso a los
datos y de cargarlos a los objetos administrados de una aplicacin, comienza la tarea ardua de las aplicaciones
WPF. En esencia, esto implica dos cosas:
1.
Copiar los datos desde los objetos administrados en los controles, donde los datos se pueden mostrar
y editar.
2.
Asegurarse de que los cambios realizados en los datos mediante los controles se vuelvan a copiar en
los objetos administrados.
Pag 11 de 445
En el ejemplo siguiente se muestra cmo enlazar un control TextBox a una instancia de un objeto Person
personalizado. La implementacin de Person se muestra en el cdigo siguiente.
Namespace SDKSample
Class Person
Private _name As String = "No Name"
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
End Class
End Namespace
El marcado siguiente enlaza el control TextBox a una instancia de un objeto Person personalizado.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.DataBindingWindow">
...
<!-- Bind the TextBox to the data source (TextBox.Text to Person.Name) -->
<TextBox Name="personNameTextBox" Text="{Binding Path=Name}" />
...
</Window>
Imports System.Windows ' Window
Namespace SDKSample
Partial Public Class DataBindingWindow
Inherits Window
Public Sub New()
InitializeComponent()
' Create Person data source
Dim person As Person = New Person()
' Make data source available for binding
Me.DataContext = person
End Sub
End Class
End Namespace
En este ejemplo, se crea una instancia de la clase Person en el cdigo subyacente y se establece como el
contexto de datos de DataBindingWindow. En el marcado, la propiedad Text de TextBox se enlaza a la
propiedad Person.Name (mediante la sintaxis "{Binding ... }" de XAML). Este cdigo XAML indica a WPF que
enlace el control TextBox al objeto Person almacenado en la propiedad DataContext de la ventana.
El motor de enlace de datos de WPF proporciona compatibilidad adicional que incluye validacin, ordenacin,
filtrado y agrupacin. Adems, el enlace de datos admite el uso de plantillas de datos, a fin de crear una
interfaz de usuario personalizada para los datos enlazados cuando la interfaz de usuario mostrada por los
controles estndar de WPF no es adecuada.
Grficos
WPF presenta un conjunto extenso, escalable y flexible de caractersticas de grficos que aportan las ventajas
siguientes:
Pag 12 de 445
Precisin mejorada. El sistema de coordenadas de WPF se mide con nmeros de punto flotante de
precisin doble, en lugar de precisin simple. Las transformaciones y los valores de opacidad tambin
se expresan como doble precisin. WPF admite tambin una amplia gama de colores (scRGB) y
proporciona compatibilidad integrada para administrar las entradas desde espacios de color diferentes.
Aceleracin de hardware. El sistema de grficos de WPF saca partido del hardware de grficos para
minimizar el uso de la CPU.
Formas 2D
WPF proporciona una biblioteca de formas 2D comunes dibujadas mediante vectores, como los rectngulos y
las elipses que se muestran en la ilustracin siguiente.
Una funcin interesante de las formas es que no sirven nicamente para su presentacin; las formas
implementan muchas de las caractersticas que cabe esperar de los controles, incluida la entrada de datos
desde el teclado y el mouse. En el ejemplo siguiente se muestra el control del evento MouseUp de una forma
Ellipse.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.EllipseEventHandlingWindow"
Title="Click the Ellipse">
<Ellipse Name="clickableEllipse" Fill="Blue"
MouseUp="clickableEllipse_MouseUp" />
</Window>
Imports System.Windows ' Window, MessageBox
Imports System.Windows.Input ' MouseButtonEventArgs
Namespace SDKSample
Public Class EllipseEventHandlingWindow
Inherits Window
Public Sub New()
InitializeComponent()
End Sub
Private Sub clickableEllipse_MouseUp(ByVal sender As Object,
ByVal e As MouseButtonEventArgs)
MessageBox.Show("You clicked the ellipse!")
End Sub
End Class
End Namespace
En la ilustracin siguiente se muestra lo que el cdigo anterior genera.
Pag 13 de 445
Geometras 2D
Las formas 2D proporcionadas por WPF abarcan el conjunto estndar de formas bsicas. Sin embargo, puede
que sea preciso crear formas personalizadas para facilitar el diseo de una interfaz de usuario personalizada.
Para este fin, WPF proporciona las geometras. En la ilustracin siguiente se muestra el uso de geometras para
crear una forma personalizada que se puede dibujar directamente, utilizar como un pincel o utilizar para
recortar otras formas y controles.
Los objetos Path se pueden utilizar para dibujar formas cerradas o abiertas, varias formas o incluso formas
curvas.
Los objetos Geometry se pueden utilizar para el recorte, la comprobacin de visitas y la representacin de
datos de grficos 2D.
Efectos 2D
Un subconjunto de las funciones 2D de WPF son los efectos visuales, tales como degradados, mapas de bits,
dibujos, pintar con vdeos, rotacin, ajuste de escala y sesgo. Todas ellas se aplican mediante pinceles; en la
siguiente ilustracin se muestran algunos ejemplos.
Representacin 3D
WPF tambin incluye funciones de representacin 3D que se integran con los grficos 2D para permitir la
creacin de UIs ms interesantes y apasionantes. Por ejemplo, en la ilustracin siguiente se muestran
imgenes 2D representadas en formas 3D.
Animacin
Pag 14 de 445
Multimedia
Una manera de mostrar un contenido enriquecido es utilizar medios audiovisuales (multimedia). WPF
proporciona compatibilidad especial con imgenes, vdeo y audio.
Imgenes
Las imgenes estn presentes en la mayora de las aplicaciones y WPF proporciona varias maneras de
utilizarlas. En la ilustracin siguiente se muestra una interfaz de usuario con un cuadro de lista que contiene
imgenes en miniatura. Cuando se selecciona una miniatura, aparece la imagen a tamao completo.
Vdeo y audio
El control MediaElement es capaz de reproducir vdeo y audio y presenta la flexibilidad suficiente para constituir
la base de un reproductor multimedia personalizado. El marcado XAML siguiente implementa un reproductor
multimedia.
<MediaElement
Name="myMediaElement"
Source="media/wpf.wmv"
LoadedBehavior="Manual"
Width="350" Height="250" />
En la ventana de la ilustracin siguiente se muestra el control MediaElement en accin.
Texto y tipografa
Para facilitar una representacin de texto de gran calidad, WPF ofrece las caractersticas siguientes:
Pag 15 de 445
Documentos
WPF permite trabajar de forma nativa con tres tipos de documentos: documentos de flujo, documentos fijos y
documentos de XML Paper Specification (XPS). WPF proporciona tambin servicios para crear, ver, administrar,
anotar, empaquetar e imprimir documentos.
Documentos dinmicos
Los documentos dinmicos se han diseado para optimizar su presentacin y legibilidad ajustando
dinmicamente su contenido y modificando su flujo cuando se producen cambios en el tamao de la ventana y
la configuracin de pantalla. En el marcado XAML siguiente se muestra la definicin de FlowDocument.
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Paragraph FontSize="18" FontWeight="Bold">Flow Document</Paragraph>
<Paragraph>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat
volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo
consequat. Duis autem vel eum iriure.
</Paragraph>
...
</FlowDocument>
En el ejemplo siguiente se muestra cmo cargar un documento dinmico en FlowDocumentReader para leerlo,
realizar bsquedas e imprimirlo.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.FlowDocumentReaderWindow"
Title="Flow Document Reader">
<FlowDocumentReader Name="flowDocumentReader" />
</Window>
Imports System.Windows 'Window
Imports System.Windows.Documents 'FlowDocument
Imports System.IO 'FileStream, FileMode
Imports System.Windows.Markup 'XamlReader
Namespace SDKSample
Public Class FlowDocumentReaderWindow
Inherits Window
Public Sub New()
Me.InitializeComponent()
Using stream1 As FileStream = _
New FileStream("AFlowDocument.xaml", _
FileMode.Open, FileAccess.Read)
Dim document1 As FlowDocument = _
TryCast(XamlReader.Load(stream1), FlowDocument)
Me.flowDocumentReader.Document = document1
End Using
End Sub
End Class
End Namespace
En el ejemplo siguiente se muestra el resultado.
Documentos fijos
Pag 16 de 445
Empaquetado de documentos XPS como archivos ZipPackage conformes con la especificacin Open
Packaging Conventions (OPC).
DocumentViewer tambin permite a los usuarios cambiar la vista de los documentos XPS, realizar bsquedas en
ellos e imprimirlos.
Anotaciones
Las anotaciones son notas o comentarios que se agregan a los documentos para marcar la informacin o
resaltar elementos de inters, a fin de consultarlos ms adelante. Aunque escribir notas en documentos
impresos es fcil, la posibilidad de "escribir" notas en los documentos electrnicos con frecuencia es limitada o
no est disponible en absoluto. Sin embargo, en WPF se proporciona un sistema de anotaciones que admite la
insercin de notas rpidas y el resaltado. Adems, estas anotaciones se pueden aplicar a documentos
hospedados en el control DocumentViewer, como se muestra en la ilustracin siguiente.
Pag 17 de 445
Empaquetado
Las API System.IO.Packaging de WPF permiten que las aplicaciones organicen los datos, el contenido y los
recursos en un nico documento ZIP porttil, sencillo de distribuir y de fcil acceso. Es posible incluir firmas
digitales para autenticar los elementos contenidos en un paquete y comprobar que el elemento firmado no se
haya manipulado ni modificado. Tambin puede cifrar los paquetes mediante la administracin de derechos
para restringir el acceso a la informacin protegida.
Impresin
.NET Framework incluye un subsistema de impresin al que WPF aporta, adems, compatibilidad con el control
de sistemas de impresin mejorados. Las mejoras de impresin incluyen las siguientes:
Los documentos XPS presenta, adems, una mejora fundamental del rendimiento. La ruta de acceso de Interfaz
de dispositivo grfico de Microsoft Windows (GDI) de impresin suele requerir dos conversiones:
Una segunda conversin al lenguaje de descripcin de pginas de la impresora, como PCL o PostScript.
Sin embargo, los documentos XPS evitan estas conversiones porque un componente del formato de archivo XPS
es un lenguaje de procesador de impresin y un lenguaje de descripcin de pginas. Esta compatibilidad ayuda
a reducir tamao del archivo de cola y las cargas de las impresoras integradas en red.
Personalizar las aplicaciones WPF
Hasta este punto, hemos estudiado las unidades de creacin de WPF fundamentales para la programacin de
aplicaciones. El modelo de aplicacin se utiliza para hospedar y distribuir el contenido de las aplicaciones, que
est compuesto principalmente de controles. Para simplificar la organizacin de los controles en una interfaz de
usuario y asegurarse de que la organizacin se conserve aunque se modifiquen el tamao de la ventana y la
configuracin de pantalla, se utiliza el sistema de diseo de WPF. Dado que la mayora de las aplicaciones
permiten a los usuarios interactuar con los datos, los enlaces de datos se utilizan para reducir el trabajo de
integracin de la interfaz de usuario con esos datos. A fin de mejorar la apariencia visual de la aplicacin, se
utiliza toda la gama de grficos, animacin y multimedia que WPF proporciona. Por ltimo, si la aplicacin
funciona a travs de texto y documentos, puede utilizar las funciones de tipografa, documentos, anotacin,
empaquetado e impresin de WPF.
Sin embargo, con frecuencia estos elementos fundamentales no bastan para crear y administrar una
experiencia del usuario realmente diferenciada y visualmente impactante. Puede que los controles de WPF no se
integren con la apariencia deseada de la aplicacin. Es posible que los datos no se muestren del modo ms
eficaz. La apariencia y el funcionamiento predeterminados de los temas de Windows pueden no ser adecuados
para proporcionar la experiencia global del usuario con respecto a la aplicacin. En muchos aspectos, una
tecnologa de presentacin requiere la extensibilidad visual tanto como cualquier otro tipo de extensibilidad.
Pag 18 de 445
Otros controles, sin embargo, pueden contener varios elementos con tipos diferentes de contenido; el contenido
de un control Button, especificado por la propiedad Content, puede contener gran variedad de elementos, entre
los que se incluyen controles de diseo, texto, imgenes y formas. En el ejemplo siguiente se muestra un
control Button con contenido que incluye DockPanel, Label, Border y MediaElement.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.ButtonContentWindow"
Title="Button Content">
...
<Button Margin="20">
<!-- Button Content -->
<DockPanel Width="200" Height="180">
<Label DockPanel.Dock="Top" HorizontalAlignment="Center">
Click Me!</Label>
<Border Background="Black" BorderBrush="Yellow" BorderThickness="2"
CornerRadius="2" Margin="5">
<MediaElement Source="media/wpf.wmv" Stretch="Fill" />
</Border>
</DockPanel>
</Button>
...
</Window>
En la ilustracin siguiente se muestra el contenido de este botn.
Desencadenadores
Aunque el propsito principal del marcado XAML es implementar la apariencia de una aplicacin, tambin puede
utilizar XAML para implementar algunos aspectos del comportamiento de una aplicacin. Un ejemplo de ello es
el uso de desencadenadores para cambiar la apariencia de una aplicacin de acuerdo con las interacciones con
el usuario.
Plantillas de control
Pag 19 de 445
Plantillas de datos
Mientras que una plantilla de control permite especificar la apariencia de un control, una plantilla de datos
permite especificar la apariencia del contenido del control. Las plantillas de datos se utilizan con frecuencia para
mejorar la manera de mostrar los datos enlazados. En la ilustracin siguiente se muestra la apariencia
predeterminada de un control ListBox enlazado a una coleccin de objetos Task, donde cada tarea tiene un
nombre, descripcin y prioridad.
Pag 20 de 445
La apariencia predeterminada es la que cabra esperar de un control ListBox. Sin embargo, la apariencia
predeterminada de cada tarea contiene nicamente el nombre de tarea. Para mostrar el nombre de tarea, la
descripcin y la prioridad, la apariencia predeterminada de los elementos de lista enlazados al control ListBox
se debe modificar, mediante DataTemplate. En el cdigo XAML siguiente se define una plantilla de datos
DataTemplate, que se aplica a cada tarea mediante el atributo ItemTemplate.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.DataTemplateWindow"
Title="With a Data Template">
...
<!-- Data Template (applied to each bound task item in the task collection) -->
<DataTemplate x:Key="myTaskTemplate">
<Border Name="border" BorderBrush="DarkSlateBlue" BorderThickness="2"
CornerRadius="2" Padding="5" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Padding="0,0,5,0"
Text="Task Name:"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding
Path=TaskName}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Padding="0,0,5,0"
Text="Description:"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding
Path=Description}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Padding="0,0,5,0"
Text="Priority:"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding
Path=Priority}"/>
</Grid>
</Border>
</DataTemplate>
...
<!-- Data template is specified by the ItemTemplate attribute -->
<ListBox
ItemsSource="{Binding}"
ItemTemplate="{StaticResource myTaskTemplate}"
HorizontalContentAlignment="Stretch"
IsSynchronizedWithCurrentItem="True"
Margin="5,0,5,5" />
...
</Window>
En la ilustracin siguiente se muestra el efecto de este cdigo.
Pag 21 de 445
Recursos
Los controles de una aplicacin deben tener la misma apariencia, que puede incluir todo tipo de recursos, desde
fuentes y colores de fondo hasta plantillas de control, pasando por las plantillas de datos y los estilos. Puede
utilizar la compatibilidad de WPF con los recursos de interfaz de usuario (UI) para encapsular estos recursos en
una ubicacin nica y poder reutilizarlos.
En el ejemplo siguiente se define un color de fondo comn que es compartido por los controles Button y Label.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.ResourcesWindow"
Title="Resources Window">
<!-- Define window-scoped background color resource -->
<Window.Resources>
<SolidColorBrush x:Key="defaultBackground" Color="Red" />
</Window.Resources>
...
<!-- Button background is defined by window-scoped resource -->
<Button Background="{StaticResource defaultBackground}">One Button</Button>
<!-- Label background is defined by window-scoped resource -->
<Label Background="{StaticResource defaultBackground}">One Label</Label>
...
</Window>
En este ejemplo se implementa un recurso de color de fondo mediante el elemento de propiedad
Window.Resources. Este recurso est disponible para todos los elementos secundarios de Window. Existe gran
variedad de mbitos de recursos, incluidos los siguiente, que se muestran en el orden en que se resuelven:
1.
2.
3.
La variedad de mbitos aporta flexibilidad al programador con respecto a la manera de definir y compartir los
recursos.
Como alternativa a la asociacin directa de los recursos a un mbito determinado, puede empaquetar uno o
varios recursos mediante un ResourceDictionary independiente al que puede hacer referencia en otras partes de
Pag 22 de 445
Pag 23 de 445
Sin embargo, en este punto puede sacar partido de uno de los tres modelos de WPF para crear un nuevo
control. Cada modelo est destinado a un escenario concreto y exige que el control personalizado se derive de
una clase base de WPF determinada. A continuacin se muestran los tres modelos:
Pag 24 de 445
Como sucede con cualquier plataforma de programacin, WPF se puede utilizar de diversas maneras
para lograr el resultado deseado. A fin de asegurarse de que sus aplicaciones WPF proporcionen la
experiencia de usuario necesaria y cumplan las exigencias del pblico en general, existen
procedimientos recomendados de accesibilidad, globalizacin y localizacin, y rendimiento.
Resumen
WPF es una completa tecnologa de presentacin para generar gran variedad aplicaciones cliente impactantes
desde el punto de vista visual. En esta introduccin se ha proporcionado una introduccin general a las
principales caractersticas de WPF.
El paso siguiente consiste en generar aplicaciones WPF.
Durante el proceso de creacin, puede consultar de nuevo esta introduccin para repasar las caractersticas
clave y encontrar referencias a artculos donde se abordan en mayor profundidad todas las caractersticas
tratadas en esta introduccin.
Definir el marcado XAML para disear la apariencia de la interfaz de usuario (UI) de la aplicacin.
Pag 25 de 445
Cuando termine el tutorial, habr generado una aplicacin independiente de Windows que permitir a los
usuarios ver los informes de gastos de las personas seleccionadas. La aplicacin constar de varias pginas de
WPF hospedadas en una ventana del estilo del explorador.
Crear los archivos de cdigo de la aplicacin
En este paso, crear la infraestructura de la aplicacin, que incluye una definicin de aplicacin, dos pginas y
una imagen.
1.
Cree un nuevo archivo de marcado XAML denominado App.xaml. Este archivo define una aplicacin de
WPF y tambin se utiliza para especificar la interfaz de usuario que debe mostrarse automticamente
cuando se inicia la aplicacin; en este caso, HomePage.xaml (que se crear en el paso siguiente). El
2.
3.
4.
Pag 26 de 445
5.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ExpenseIt.ExpenseReportPage"
Title="ExpenseIt - View Expense Report">
</Page>
Cree un nuevo archivo denominado ExpenseReportPage.xaml.cs. Este archivo ser un archivo de
cdigo subyacente que enlace los datos del informe de gastos a la interfaz de usuario definida en
6.
En este paso, utilizar MSBuild para generar la aplicacin que defini en la seccin anterior.
1.
Cree un nuevo archivo denominado ExpenseIt.csproj. Este archivo ser el archivo de MSBuild, que es
un archivo XML especial que contiene la configuracin de compilacin de su aplicacin e incluye los
siguientes elementos:
Las variables de compilacin globales para el proyecto compilado, como el nombre del
ensamblado generado, el tipo de ensamblado que debe generarse y la carpeta en la que debe
agregarse el ensamblado generado.
2.
El contenido del archivo de compilacin debe ser similar al que se muestra a continuacin:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AssemblyName>ExpenseIt</AssemblyName>
<TargetType>winexe</TargetType>
<OutputPath>bin\$(Configuration)\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Xml"/>
<Reference Include="System.Data"/>
<Reference Include="WindowsBase"/>
<Reference Include="PresentationCore"/>
<Reference Include="PresentationFramework"/>
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml"/>
<Page Include="HomePage.xaml"/>
<Compile Include="HomePage.xaml.cs" />
<Page Include="ExpenseReportPage.xaml"/>
<Compile Include="ExpenseReportPage.xaml.cs" />
<Resource Include="watermark.png"/>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets"/>
<Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets"/>
</Project>
Abra una ventana de comandos en la misma carpeta donde se encuentra el archivo de proyecto y los
archivos de cdigo de la aplicacin.
3.
Pag 27 de 445
Abra la carpeta que contiene el archivo ejecutable de la aplicacin generado, es decir, expenseit.exe.
En caso de que haya generado el archivo desde el smbolo del sistema, expenseit.exe se encontrar en la
carpeta siguiente:
Carpeta que contiene los archivos de cdigo de la aplicacin \bin\
Si ha generado el archivo utilizando Visual Studio, expenseit.exe se encontrar en la carpeta siguiente:
Carpeta que contiene los archivos de cdigo de la aplicacin \bin\debug\
2.
Agregar el diseo
El diseo proporciona un modo ordenado de colocar los elementos de la interfaz de usuario, y tambin controla
el tamao y la posicin de los mismos cuando la interfaz de usuario cambia de tamao. Normalmente, para
agregar el diseo a la interfaz de usuario se utiliza uno de los controles de diseo siguientes:
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Cada uno de ellos admite un tipo de diseo especial para sus elementos secundarios. Es posible cambiar de
tamao las pginas de ExpenseIt, y cada pgina tiene elementos organizados horizontal y verticalmente junto
con otros elementos. Por lo tanto, Grid es el elemento de diseo ideal para la aplicacin.
El marcado XAML siguiente crea una tabla de una columna y tres filas, con un margen de 10 pxeles, agregando
un control Grid a HomePage.xaml:
1.
Abra HomePage.xaml.
2.
Pag 28 de 445
2.
La imagen siguiente muestra los controles creados por el cdigo de este paso.
Abra HomePage.xaml.
2.
Pag 29 de 445
3.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ExpenseIt.HomePage"
WindowTitle="ExpenseIt"
Title="ExpenseIt - Home"
WindowWidth="550" WindowHeight="380">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="230" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
<Canvas DockPanel.Dock="Left" Width="230" Height="100">
<Image Source="watermark.png" />
</Canvas>
<Label VerticalAlignment="Center" FontFamily="Trebuchet MS"
FontWeight="Bold" FontSize="18" Foreground="#0066cc">
View Expense Report
</Label>
</DockPanel>
<Grid Margin="10" Grid.Column="1" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- People list -->
<Border Grid.Column="0" Grid.Row="0" Height="35" Padding="5"
Background="#4E87D4">
<Label VerticalAlignment="Center" Foreground="White">Names
</Label>
</Border>
<ListBox Name="peopleListBox" Grid.Column="0" Grid.Row="1">
<ListBoxItem>Mike</ListBoxItem>
<ListBoxItem>Lisa</ListBoxItem>
<ListBoxItem>John</ListBoxItem>
<ListBoxItem>Mary</ListBoxItem>
</ListBox>
<!-- View report button -->
<Button Grid.Column="0" Grid.Row="2" Margin="0,10,0,0"
Width="125" Height="25" HorizontalAlignment="Right">View</Button>
</Grid>
</Grid>
</Page>
Este cdigo XAML actualiza el control Grid de las formas siguientes:
Utiliza el atributo Source del elemento Image para especificar la imagen de origen, es decir,
watermark.png.
4.
Pag 30 de 445
Abra HomePage.xaml.
2.
3.
Abra el archivo HomePage.xaml.cs que cre en el paso Crear los archivos de cdigo de la aplicacin del
tutorial.
4.
Sobrescriba el contenido del archivo por el siguiente cdigo. De esta forma, se agrega cdigo para
controlar el evento Click, que permite navegar hasta el archivo ExpenseReportPage.xaml.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace ExpenseIt
{
public partial class HomePage : Page
{
public HomePage()
{
InitializeComponent();
}
private void viewButton_Click(object sender, RoutedEventArgs args)
{
// View Expense Report
ExpenseReportPage expenseReportPage = new ExpenseReportPage();
this.NavigationService.Navigate(expenseReportPage);
}
}
}
Crear la interfaz de usuario para ExpenseReportPage
Pag 31 de 445
2.
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
<Canvas DockPanel.Dock="Left" Width="230" Height="100">
<Image Source="watermark.png" />
</Canvas>
<Label VerticalAlignment="Center" FontFamily="Trebuchet MS"
FontWeight="Bold" FontSize="18" Foreground="#0066cc">
Expense Report For:
</Label>
</DockPanel>
<Grid Margin="10" Grid.Column="1" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Name -->
<StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0"
Orientation="Horizontal">
<Label Margin="0,0,0,5" FontWeight="Bold">Name:</Label>
<Label Margin="0,0,0,5" FontWeight="Bold"></Label>
</StackPanel>
<!-- Department -->
<StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1"
Orientation="Horizontal">
<Label Margin="0,0,0,5" FontWeight="Bold">Department:</Label>
<Label Margin="0,0,0,5" FontWeight="Bold"></Label>
</StackPanel>
<Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="10" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Expense type list -->
<Border Grid.Column="0" Grid.Row="0" Height="35" Padding="5"
Background="#4E87D4">
<Label VerticalAlignment="Center" Foreground="White">Expense
Type</Label>
</Border>
<ListBox Grid.Column="0" Grid.Row="1" />
<!-- Amount list -->
<Border Grid.Column="2" Grid.Row="0" Height="35" Padding="5"
Background="#4E87D4">
<Label VerticalAlignment="Center" Foreground="White">Amount
</Label>
</Border>
<ListBox Grid.Column="2" Grid.Row="1" />
</Grid>
</Grid>
</Grid>
</Page>
Compile y ejecute la aplicacin.
Pag 32 de 445
Abra el archivo App.xaml creado en el paso Crear los archivos de cdigo de la aplicacin de este
tutorial.
2.
3.
Observe que los estilos son los recursos secundarios del elemento de propiedad Application.Resources. En
esta ubicacin, los estilos se aplican a todos los elementos de una aplicacin.
4.
5.
Abra HomePage.xaml.
Sobrescriba el contenido del archivo por el siguiente cdigo. En este paso se reemplazan atributos
especficos de la apariencia de cada elemento por un estilo apropiado.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Pag 33 de 445
6.
7.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ExpenseIt.HomePage"
WindowTitle="ExpenseIt"
Title="ExpenseIt - Home"
WindowWidth="550" WindowHeight="380">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="230" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
<Canvas DockPanel.Dock="Left" Width="230" Height="100">
<Image Style="{StaticResource backgroundImageStyle}" />
</Canvas>
<Label Style="{StaticResource headerTextStyle}">View Expense
Report</Label>
</DockPanel>
<Grid Margin="10" Grid.Column="1" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- People list -->
<Border Grid.Column="0" Grid.Row="0" Style="{StaticResource
listHeaderStyle}">
<Label Style="{StaticResource listHeaderTextStyle}">Names
</Label>
</Border>
<ListBox Name="peopleListBox" Grid.Column="0" Grid.Row="1">
<ListBoxItem>Mike</ListBoxItem>
<ListBoxItem>Lisa</ListBoxItem>
<ListBoxItem>John</ListBoxItem>
<ListBoxItem>Mary</ListBoxItem>
</ListBox>
<!-- View report button -->
<Button Grid.Column="0" Grid.Row="2" Style="{StaticResource
buttonStyle}" Click="viewButton_Click">View</Button>
</Grid>
</Grid>
</Page>
Abra ExpenseReportPage.xaml.
Sobrescriba el contenido del archivo por el siguiente cdigo.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ExpenseIt.ExpenseReportPage"
Title="ExpenseIt - View Expense Report">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="230" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
<Canvas DockPanel.Dock="Left" Width="230" Height="100">
<Image Style="{StaticResource backgroundImageStyle}" />
</Canvas>
<Label Style="{StaticResource headerTextStyle}">Expense Report
For:</Label>
</DockPanel>
<Grid Margin="10" Grid.Column="1" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Name -->
<StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0"
Orientation="Horizontal">
Pag 34 de 445
8.
Abra HomePage.xaml.
2.
Pag 35 de 445
3.
</DataTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="230" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<DockPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0">
<Canvas DockPanel.Dock="Left" Width="230" Height="100">
<Image Style="{StaticResource backgroundImageStyle}" />
</Canvas>
<Label Style="{StaticResource headerTextStyle}">View Expense
Report</Label>
</DockPanel>
<Grid Margin="10" Grid.Column="1" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- People list -->
<Border Grid.Column="0" Grid.Row="0" Style="{StaticResource
listHeaderStyle}">
<Label Style="{StaticResource listHeaderTextStyle}">Names
</Label>
</Border>
<ListBox Name="peopleListBox" Grid.Column="0" Grid.Row="1"
ItemsSource="{Binding Source={StaticResource
ExpenseDataSource}, XPath=Person}"
ItemTemplate="{StaticResource nameItemTemplate}" />
<!-- View report button -->
<Button Grid.Column="0" Grid.Row="2" Style="{StaticResource
buttonStyle}" Click="viewButton_Click">View</Button>
</Grid>
</Grid>
</Page>
Observe que los datos se crean como un recurso Grid.
Conectar los datos a los controles
En este paso, escribir el cdigo que recupera el elemento actual que est seleccionado en la lista de personas
de HomePage y pasa su referencia al constructor de ExpenseReportPage durante la creacin de instancias.
ExpenseReportPage establece su contexto de datos con el elemento que se pasa, que es el elemento con el que
se enlazarn los controles definidos en ExpenseReportPage.xaml.
1.
Abra HomePage.xaml.cs.
2.
3.
4.
Pag 36 de 445
}
Agregar estilo a los datos con plantillas de datos
En este paso, actualizar la interfaz de usuario para cada elemento de las listas enlazadas a datos utilizando las
plantillas de datos:
1.
Abra ExpenseReportPage.xaml.
2.
Pag 37 de 445
3.
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Expense type list -->
<Border Grid.Column="0" Grid.Row="0" Style="{StaticResource
listHeaderStyle}">
<Label Style="{StaticResource listHeaderTextStyle}">Expense
Type</Label>
</Border>
<ListBox Grid.Column="0" Grid.Row="1" ItemsSource="{Binding
XPath=Expense}"
ItemTemplate="{StaticResource typeItemTemplate}" />
<!-- Amount list -->
<Border Grid.Column="2" Grid.Row="0" Style="{StaticResource
listHeaderStyle}">
<Label Style="{StaticResource listHeaderTextStyle}">Amount
</Label>
</Border>
<ListBox Grid.Column="2" Grid.Row="1" ItemsSource="{Binding
XPath=Expense}"
ItemTemplate="{StaticResource amountItemTemplate}" />
</Grid>
</Grid>
</Grid>
</Page>
Compile y ejecute la aplicacin.
Observe que las plantillas de datos estn definidas como recursos Grid.
En las dos ilustraciones siguientes se muestran las dos pginas de la aplicacin ExpenseIt con los controles, el
diseo, los estilos, el enlace de datos y las plantillas de datos aplicadas:
Pag 38 de 445
Compatibilidad completa con complementos para admitir los complementos visuales y no visuales de
aplicaciones independientes y Aplicaciones del explorador XAML (XBAPs).
Deteccin: bsqueda de complementos que se adhieran a los contratos admitidos por las aplicaciones
host.
Comunicacin: los complementos y las aplicaciones host deben poder comunicarse entre s ms all de
los lmites de aislamiento llamando a mtodos y pasando datos.
Control de versiones: garanta de que las aplicaciones host y los complementos puedan continuar
comunicndose cuando se creen nuevas versiones de cualquiera de ellos.
En lugar de exigirle que resuelva estos problemas, .NET Framework incluye ahora un conjunto de tipos,
ubicados en el espacio de nombres System.AddIn, que se conocen como el "modelo de complementos". El
modelo de complementos de .NET Framework proporciona funcionalidad para cada uno de los comportamientos
de complemento comunes que se han mencionado anteriormente.
En algunos escenarios, sin embargo, tambin puede ser conveniente permitir que los complementos se integren
con las UIs de la aplicacin host y las extiendan. WPF extiende el modelo de complementos de .NET Framework
para permitir esta compatibilidad, que se genera en torno a un objeto FrameworkElement propiedad de un
complemento en las UIs de una aplicacin host. Esto permite a los desarrolladores de WPF crear aplicaciones
compatibles con los siguientes escenarios comunes:
Aplicaciones de estilo Messenger que proporcionen servicios adicionales con complementos afines de
otros fabricantes.
Pag 39 de 445
Por ltimo, los complementos de WPF pueden ser hospedados tanto por aplicaciones independientes como por
XBAPs.
Compatibilidad con Firefox para aplicaciones XBAP
Un complemento para WPF 3.5 permite ejecutar XBAPs desde Firefox 2.0. Esta caracterstica no est disponible
en WPF 3.0. Entre las caractersticas principales se incluyen las siguientes:
Las caractersticas de seguridad disponibles para las XBAPs que se ejecutan en Internet Explorer
tambin estn disponibles para las XBAPs que se ejecutan en Firefox 2.0, incluido el recinto de
seguridad de confianza parcial. Las caractersticas de seguridad adicionales proporcionadas por el
explorador son especficas del explorador.
Cookies
Las aplicaciones WPF independientes y las XBAPs pueden crear, obtener y eliminar cookies tanto de sesin
como persistentes. En WPF 3.5, las cookies persistentes se pueden compartir entre las XBAPs, los servidores
web y los archivos HTML que tienen el mismo sitio de origen.
Mejoras de Visual Studio IntelliSense
Ahora es posible agregar un nuevo elemento XAML mediante el editor XAML de Visual Studio, asignarle un
nombre (mediante el atributo Name), hacer referencia a l desde cdigo subyacente y ver sus miembros desde
el explorador de IntelliSense.
Localizacin
WPF 3.5 agrega compatibilidad para los siguientes sistemas de escritura:
Bengal
Devanagari
Gujarati
Gurmukhi
Kannada
Malayalam
Oriya
Tamil
Telugu
CompositionOffset
CompositionLength
ResultOffset
ResultLength
Pag 40 de 445
BitmapImage.UriCachePolicy
BitmapDecoder.Create(Uri, BitmapCreateOptions, BitmapCacheOption, RequestCachePolicy)
BitmapFrame.Create(Uri, RequestCachePolicy)
BitmapFrame.Create(Uri, BitmapCreateOptions, BitmapCacheOption, RequestCachePolicy)
dos
propiedades
proporcionan
una
alternativa
establecer
ExceptionValidationRule
Pag 41 de 445
La clase TextRange tiene una nueva sobrecarga Save(Stream, String, Boolean) que acepta un valor
booleano que especifica si se deben conservar los objetos TextElement personalizados.
El control RichTextBox tiene una nueva propiedad denominada IsDocumentEnabled. Cuando el valor de
IsDocumentEnabled es true, los elementos de la interfaz de usuario, como botones e hipervnculos, aceptan los
datos proporcionados por el usuario.
TextBoxBase
TextBoxBase tiene una nueva propiedad denominada UndoLimit, que especifica el nmero mximo de acciones
a las que el control hace referencia.
SoundPlayerAction
SoundPlayerAction puede ahora cargar archivos de audio que pueden ser identificados mediante pack
identificadores de recursos uniformes (URIs) relativos y absolutos:
Thumb.IsDragging
ButtonBase.IsPressed
MenuItem.IsPressed
MenuItem.IsHighlighted
ComboBoxItem.IsHighlighted
Documentos
FlowDocumentPageViewer, FlowDocumentScrollViewer y FlowDocumentReader tienen una nueva propiedad
pblica denominada Selection. La propiedad obtiene el objeto TextSelection que representa el contenido
seleccionado en el documento.
Anotaciones
El marco de trabajo de anotaciones expone ahora las capacidades necesarias para hacer coincidir las
anotaciones con los correspondientes objetos anotados. Se ha agregado una nueva interfaz denominada
IAnchorInfo. Adems, se ha agregado un nuevo mtodo denominado GetAnchorInfo, que devuelve un objeto
IAnchorInfo, a la clase AnnotationHelper.
Pag 42 de 445
2. Desarrollo de Aplicaciones
El modelo de aplicacin est en el ncleo de todas las aplicaciones de Windows Presentation Foundation (WPF).
Esta pgina contiene vnculos a informacin general del modelo de aplicacin de WPF.
Aplicaciones del explorador XAML (XBAPs) (aplicaciones compuestas de pginas navegables que se
generan como ensamblados ejecutables que se exploran y hospedan por Windows Internet Explorer).
Bibliotecas
de
control
personalizadas
(ensamblados
no
ejecutables
que
contienen
controles
reutilizables).
Nota:
No se admite el uso de WPF para generar servicios de Windows. Dado que WPF es una tecnologa de
presentacin, el servicio de Windows requiere los permisos adecuados para realizar operaciones visuales
que requieren la interaccin con el usuario. Si el servicio de Windows no tiene los permisos adecuados,
pueden producirse resultados inesperados.
Para generar este conjunto de aplicaciones, WPF implementa un host de servicios. En este tema se proporciona
informacin general sobre estos servicios y se indica dnde buscar ms informacin.
Administracin de aplicaciones
Las aplicaciones ejecutables de WPF suelen requerir un conjunto bsico de funcionalidades, que incluye:
Crear y administrar la infraestructura de aplicaciones comn (lo que incluye crear un mtodo de punto
de entrada y un bucle de mensajes de Windows para recibir los mensajes del sistema y de entrada).
Estas funciones se implementan mediante la clase Application, que se agrega a las aplicaciones utilizando una
definicin de aplicacin. Application tiene las caractersticas siguientes.
Archivos de recursos, contenido y datos de aplicaciones de WPF
WPF aprovecha y extiende la compatibilidad bsica de Microsoft .NET Framework para los recursos incrustados
con compatibilidad para tres tipos de archivos de datos no ejecutables: de recursos, de contenido y de datos.
Un componente clave de la compatibilidad con archivos de datos no ejecutables de WPF es la capacidad de
identificarlos y cargarlos utilizando un URI nico.
Ventanas y cuadros de dilogo
Los usuarios interactan con las aplicaciones independientes de WPF por medio de ventanas. El propsito de
una ventana es hospedar contenido de la aplicacin y exponer la funcionalidad de la aplicacin que suele
Pag 43 de 445
Window admite la capacidad de crear un tipo especial de ventana denominado cuadro de dilogo. Se pueden
crear los tipos modales y no modales de cuadros de dilogo.
Para mayor comodidad y para ofrecer las ventajas de reusabilidad, as como una experiencia del usuario
uniforme en todas las aplicaciones, WPF expone tres de los cuadros de dilogo comunes de Windows, que son:
OpenFileDialog, SaveFileDialog y PrintDialog.
Un cuadro de mensaje es un tipo especial de cuadro de dilogo utilizado para mostrar informacin de texto
importante a los usuarios y plantear preguntas sencillas de S/No/Aceptar/Cancelar. Para crear y mostrar
cuadros de mensaje se utiliza la clase MessageBox.
Navegacin
WPF admite la navegacin de tipo web con pginas (Page) e hipervnculos (Hyperlink). La navegacin se puede
implementar de diversas maneras; entre otras:
Pginas hospedadas por un marco (Frame), hospedadas en una pgina que puede ser independiente o
bien compilada en una XBAP o en una aplicacin independiente.
Uso del "diario" (que se puede inspeccionar y manipular) para memorizar la navegacin hacia delante
y hacia atrs.
WPF tambin admite un tipo especial de navegacin denominado navegacin estructurada. La navegacin
estructurada se puede utilizar para llamar a una o ms pginas que devuelven datos de una manera
estructurada y previsible coherente con las funciones que realizaron las llamadas. Esta capacidad depende de la
clase PageFunction<(Of <(T>)>). PageFunction<(Of <(T>)>) tambin permite simplificar la creacin de
topologas de navegacin complejas.
Hospedaje
Las XBAPs se pueden hospedar en Microsoft Internet Explorer 6, Windows Internet Explorer 7 o Microsoft
Windows Media Center (WMC). Cada modelo de hospedaje tiene su propio conjunto de consideraciones y
restricciones.
Compilacin e implementacin
Aunque las aplicaciones de WPF simples se pueden generar desde un smbolo del sistema mediante
compiladores de lnea de comandos, WPF se integra con Microsoft build engine (MSBuild) y lo extiende a fin de
proporcionar compatibilidad adicional para simplificar el proceso de programacin y compilacin.
Pag 44 de 445
Para utilizar estos servicios en la aplicacin, necesita utilizar la clase Application para implementar una
definicin de aplicacin.
Definicin de aplicacin
Una definicin de aplicacin WPF es una clase que deriva de Application y se configura con un valor de Microsoft
build engine (MSBuild) especial.
Implementar una definicin de aplicacin
Una definicin de aplicacin WPF tpica se implementa utilizando tanto marcado como cdigo subyacente. Esto
permite utilizar marcado para establecer mediante declaracin propiedades, recursos y eventos de registro de
la aplicacin, mientras que el control de eventos y la implementacin del comportamiento especfico de la
aplicacin se realizan en el cdigo subyacente.
En el ejemplo siguiente se muestra cmo implementar una definicin de aplicacin utilizando tanto marcado
como cdigo subyacente:
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App" />
using System.Windows; // Application
namespace SDKSample
{
public partial class App : Application { }
}
Pag 45 de 445
declaracin
de
espacio
de
nombres
XML
para
el
esquema
XAML
(xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml").
En el archivo de cdigo subyacente, la clase debe ser una clase partial con el mismo nombre que el
especificado por el atributo x:Class en el marcado, y debe derivarse de Application. Esto permite que
el archivo de cdigo subyacente se asocie a la clase partial que se genera para el archivo de marcado
cuando se genera la aplicacin.
Nota:
Al crearse un nuevo proyecto de Aplicacin WPF o Aplicacin de explorador WPF mediante Microsoft Visual
Studio, se incluye de forma predeterminada una definicin de aplicacin, que se define utilizando tanto
marcado como cdigo subyacente.
Este cdigo es el mnimo necesario para implementar una definicin de aplicacin. Sin embargo, es necesario
realizar una configuracin adicional de MSBuild en la definicin de aplicacin antes de generar y ejecutar la
aplicacin.
Configurar la definicin de aplicacin para MSBuild
Las aplicaciones independientes y Aplicaciones del explorador XAML (XBAPs) requieren la implementacin de un
cierto nivel de infraestructura para poderse ejecutar. La parte ms importante de esta infraestructura es el
punto de entrada. Cuando un usuario inicia una aplicacin, el sistema operativo llama al punto de entrada, que
es una funcin conocida para iniciar las aplicaciones.
Tradicionalmente, los desarrolladores necesitaban escribir todo o parte de este cdigo, segn la tecnologa. Sin
embargo, WPF se encarga de generar este cdigo cuando el archivo de marcado de la definicin de aplicacin
est configurado como un elemento MSBuildApplicationDefinition, tal como se muestra en el siguiente archivo
de proyecto de MSBuild:
<Project
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<ApplicationDefinition Include="App.xaml" />
<Compile Include="App.xaml.cs" />
...
</Project>
Dado que el archivo de cdigo subyacente contiene cdigo, se marca como un elemento MSBuildCompile, lo
cual es normal.
La aplicacin de estas configuraciones de MSBuild a los archivos de cdigo subyacente y marcado de una
definicin de aplicacin hace que MSBuild genere cdigo como el siguiente:
using System; // STAThread
using System.Windows; // Application
namespace SDKSample
{
public class App : Application
{
public App() { }
[STAThread]
public static void Main()
{
// Create new instance of application subclass
App app = new App();
// Code to register events and set properties that were
// defined in XAML in the application definition
app.InitializeComponent();
// Start running the application
app.Run();
}
public void InitializeComponent()
{
...
}
Pag 46 de 445
WPF. Cuando
se
invoca,
Main crea
una
nueva
instancia
de
App
antes
de
llamar
al
mtodo InitializeComponent para registrar los eventos y establecer las propiedades que se implementan en el
marcado. Dado que se genera InitializeComponent, no es necesario llamar explcitamente a InitializeComponent
desde una definicin de aplicacin tal y como se hace para las implementaciones de Page y Window.
Finalmente, se llama al mtodo Run para iniciar la aplicacin.
Obtener la aplicacin actual
Dado que los servicios de la clase Application se comparten en una aplicacin, puede haber solamente una
instancia de la clase Application por AppDomain. Para exigir esto, la clase Application se implementa como una
clase singleton, que crea una nica instancia de s misma y proporciona acceso compartido a ella con la
propiedad static Current.
En el cdigo siguiente se muestra cmo adquirir una referencia al objeto Application para el objeto AppDomain
actual.
// Get current application
Application current = App.Current;
Current devuelve una referencia a una instancia de la clase Application. Si desea obtener una referencia a la
clase derivada de Application, debe convertir el valor de la propiedad Current, como se muestra en el ejemplo
siguiente.
// Get strongly-typed current application
App app = (App)App.Current;
Puede inspeccionar el valor de Current en cualquier punto de la duracin de un objeto Application. Sin
embargo, se recomienda tener cuidado. Tras crearse una instancia de la clase Application, el estado del objeto
Application es incoherente durante un perodo de tiempo. Durante este perodo, Application realiza las diversas
tareas de inicializacin necesarias para que se ejecute el cdigo, incluido el establecimiento de la
infraestructura de la aplicacin, la configuracin de las propiedades y el registro de los eventos. Si intenta
utilizar el objeto Application durante este perodo, el cdigo puede generar resultados inesperados, en particular
si depende de las diversas propiedades de Application que se estn estableciendo.
Cuando Application completa sus tareas de inicializacin, se inicia realmente su duracin.
Duracin de la aplicacin
La duracin de una aplicacin WPF est marcada por varios eventos que Application provoca para indicar
cundo se inicia la aplicacin, cundo se activa y se desactiva, y cundo se cierra.
Iniciar una aplicacin
Despus de llamarse a Run e inicializarse la aplicacin, esta est lista para ejecutarse. El evento Startup indica
este momento:
using System.Windows; // Application, StartupEventArgs, WindowState
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Application is running
...
}
}
}
En este punto de la duracin de una aplicacin, se suele mostrar una interfaz de usuario.
Mostrar una interfaz de usuario
Pag 47 de 445
Pag 48 de 445
Para detectar cundo una aplicacin se convierte en la aplicacin activa, controle el evento Activated.
De manera similar, una aplicacin puede volverse inactiva en las circunstancias siguientes:
Pag 49 de 445
Para detectar cundo una aplicacin se vuelve inactiva, controle el evento Application.Deactivated.
En el cdigo siguiente se muestra cmo controlar los eventos Activated y Deactivated para determinar si una
aplicacin est activa.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
Activated="App_Activated"
Deactivated="App_Deactivated" />
using System; // EventArgs
using System.Windows; // Application
namespace SDKSample
{
public partial class App : Application
{
bool isApplicationActive;
void App_Activated(object sender, EventArgs e)
{
// Application activated
this.isApplicationActive = true;
}
void App_Deactivated(object sender, EventArgs e)
{
// Application deactivated
this.isApplicationActive = false;
}
}
}
Un objeto Window tambin se puede activar y desactivar.
Nota:
En el caso de las XBAPs, no se provoca el evento Application.Activated ni el evento Application.Deactivated.
Cierre de la aplicacin
La duracin de una aplicacin finaliza cuando se cierra, lo cual puede ocurrir por las razones siguientes:
Para facilitar la administracin del cierre de la aplicacin, Application proporciona el mtodo Shutdown, la
propiedad ShutdownMode y los eventos SessionEnding y Exit.
Nota:
Solamente se puede llamar a Shutdown desde aplicaciones que tengan UIPermission. Las aplicaciones WPF
independientes siempre tienen este permiso. Sin embargo, las XBAPs que se ejecutan en el recinto de
seguridad de confianza parcial de la zona de Internet no lo tienen.
Modo de apagado
La mayora de las aplicaciones se apagan cuando se cierran todas las ventanas o cuando se cierra la ventana
principal. En ocasiones, sin embargo, puede haber otras condiciones especficas de la aplicacin que determinen
cundo se cierra la aplicacin. Puede especificar las condiciones en las que se cerrar la aplicacin
estableciendo la propiedad ShutdownMode en uno de los valores siguientes de la enumeracin ShutdownMode:
OnLastWindowClose
OnMainWindowClose
OnExplicitShutdown
El valor predeterminado de ShutdownMode es OnLastWindowClose, lo que significa que una aplicacin se cierra
automticamente cuando el usuario cierra la ltima ventana de la aplicacin. Sin embargo, si la aplicacin debe
Pag 50 de 445
ShutdownMode
en
Cerrar sesin
Apagar
Reiniciar
Hibernar
Para detectar cundo finaliza una sesin de Windows, puede controlar el evento SessionEnding, tal como se
muestra en el ejemplo siguiente.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
SessionEnding="App_SessionEnding" />
using System.Windows; // Application, SessionEndingCancelEventArgs, MessageBox,
MessageBoxResult, MessageBoxButton
namespace SDKSample
{
public partial class App : Application
{
void App_SessionEnding(object sender, SessionEndingCancelEventArgs e)
{
// Ask the user if they want to allow the session to end
string msg = string.Format("{0}. End session?",
e.ReasonSessionEnding);
MessageBoxResult result = MessageBox.Show(msg, "Session
Ending", MessageBoxButton.YesNo);
// End session, if specified
if (result == MessageBoxResult.No)
{
e.Cancel = true;
}
}
}
}
En este ejemplo, el cdigo inspecciona la propiedad ReasonSessionEnding para determinar cmo finaliza la
sesin de Windows. Utiliza este valor para mostrar un mensaje de confirmacin al usuario. Si el usuario no
desea que la sesin finalice, el cdigo establece Cancel en true para evitar que finalice la sesin de Windows.
Nota:
No se provoca el evento SessionEnding para las XBAPs.
Salir
Cuando una aplicacin se apaga, es posible que necesite realizar algunos ltimos procesos, como conservar el
estado de la aplicacin. Para estas situaciones, puede controlar el evento Exit.
<Application
Pag 51 de 445
Cdigo de salida
La mayora de las aplicaciones las inicia el sistema operativo en respuesta a una solicitud del usuario. Sin
embargo, una aplicacin puede ser iniciada por otra aplicacin para realizar alguna tarea concreta. Cuando la
aplicacin iniciada se cierra, es posible que la aplicacin que la inici desee conocer la condicin en la que se
cerr la aplicacin iniciada. En estas situaciones, Windows permite que las aplicaciones devuelvan un cdigo de
salida al cerrarse. De forma predeterminada, las aplicaciones WPF devuelven 0 como valor de cdigo de salida.
Nota:
Cuando se depura desde Visual Studio, el cdigo de salida de la aplicacin se muestra en la ventana
Resultados cuando se cierra la aplicacin, en un mensaje similar al siguiente:
The program '[5340] AWPFApp.vshost.exe: Managed' has exited with code 0 (0x0).
Para abrir la ventana Resultados, haga clic en Resultados en el men Ver.
Para cambiar el cdigo de salida, puede llamar a la sobrecarga Shutdown(Int32), que acepta un argumento de
tipo entero como cdigo de salida:
// Shutdown and return a non-default exit code
Application.Current.Shutdown(-1);
Para detectar el valor del cdigo de salida y cambiarlo, controle el evento Exit. Al controlador de eventos Exit se
le
pasa
un
objeto
ExitEventArgs
que
proporciona
acceso
al
cdigo
de
salida
con
la
propiedad
ApplicationExitCode.
Nota:
El cdigo de salida puede establecerse tanto en las aplicaciones independientes como en las XBAPs. Sin
embargo, el valor del cdigo de salida se omite para las XBAPs.
Excepciones no controladas
A veces, puede que una aplicacin se cierre en condiciones irregulares, como cuando se produce una excepcin
imprevista. En este caso, es posible que la aplicacin no tenga el cdigo necesario para detectar y procesar la
excepcin. Este tipo de excepcin es una excepcin no controlada; se muestra una notificacin similar a la que
aparece en la figura siguiente antes de que se cierre la aplicacin.
Pag 52 de 445
Al
un
parmetro
anteriormente.
Si
se
produce
una
excepcin
no
controlada
no
se
controla
el
evento
Pag 53 de 445
Igualmente, en la figura siguiente se muestran los eventos clave a lo largo de la duracin de una aplicacin
XBAP y la secuencia en la que se provocan.
GetResourceStream
Pag 54 de 445
GetContentStream
GetRemoteStream
Administracin de ventanas
Application y Window tienen una relacin estrecha. Como se ha mencionado anteriormente, la duracin de una
aplicacin puede depender de la duracin de sus ventanas, segn lo especificado por la propiedad
ShutdownMode. Application registra qu ventana se designa como ventana principal de la aplicacin
(MainWindow) y mantiene una lista de las ventanas de las que se han creado instancias (Windows).
Administracin de la navegacin
Para las aplicaciones independientes con navegacin (que utilizan NavigationWindow y Frame) o XBAPs,
Application detecta cualquier navegacin dentro de una aplicacin y provoca los siguientes eventos segn
corresponda:
Navigating
Navigated
NavigationProgress
NavigationFailed
NavigationStopped
LoadCompleted
FragmentNavigation
Adems, Application permite a las aplicaciones de cualquier tipo crear, conservar y recuperar cookies, mediante
los mtodos GetCookie y SetCookie.
Archivos de contenido: archivos de datos independientes que tienen una asociacin explcita con un
ensamblado ejecutable de WPF.
Archivos de sitio de origen: archivos de datos independientes que no tienen ninguna asociacin con un
ensamblado ejecutable de WPF.
Hay una diferencia importante entre estos tres tipos de archivos: los archivos de recursos y los archivos de
contenido se conocen en tiempo de compilacin; un ensamblado tiene conocimiento explcito de ellos. En el
caso de los archivos de sitio de origen, sin embargo, es posible que el ensamblado no tenga conocimiento de
ellos o tenga un conocimiento implcito a travs de una referencia de pack identificador de recursos uniforme
(URI); en este ltimo caso, no hay ninguna garanta de que exista realmente el archivo de sitio de origen al que
se hace referencia.
Para hacer referencia a los archivos de datos de aplicacin, Windows Presentation Foundation (WPF) utiliza el
esquema de pack identificador de recursos uniforme (URI).
En este tema se describe cmo configurar y utilizar los archivos de datos de aplicacin.
Archivos de recursos
Si un archivo de datos de aplicacin debe estar siempre disponible para una aplicacin, la nica manera de
garantizar la disponibilidad es generarlo en el ensamblado ejecutable principal de una aplicacin o en uno de los
Pag 55 de 445
No es necesario actualizar el contenido del archivo de recursos una vez generado en un ensamblado.
Se desea simplificar la distribucin de la aplicacin reduciendo el nmero de dependencias de archivo.
El archivo de datos de aplicacin debe ser localizable.
Nota:
Los diccionarios de recursos (archivos XAML con ResourceDictionary como su elemento de nivel superior)
no son archivos de recursos de WPF; aunque los archivos de recursos de WPF pueden ser diccionarios de
recursos, un diccionario de recursos no tiene que ser necesariamente un archivo de recursos.
Adems, los archivos de recursos de WPF no son los mismos que el tipo de recursos incrustados o
vinculados que se pueden configurar usando la compatibilidad bsica de .NET Framework con los recursos
de ensamblado (vea). Si bien los archivos de recursos de WPF aprovechan la compatibilidad bsica con los
recursos incrustados de .NET Framework, el acceso a los archivos de recursos de WPF mediante pack URIs
resulta ms fcil que el uso de espacios de nombres.
Configurar archivos de recursos
En WPF, un archivo de recursos es un archivo que est incluido en un proyecto de Microsoft build engine
(MSBuild) como un elemento Resource.
<Project "xmlns=http://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Resource Include="ResourceFile.xaml" />
</ItemGroup>
...
</Project>
Nota:
En Microsoft Visual Studio, se crea un archivo de recursos agregando un archivo a un proyecto y
estableciendo el valor de Build Action en Resource.
Una vez generado el proyecto, MSBuild genera el recurso en el ensamblado.
Usar archivos de recursos
Para cargar un archivo de recursos, puede llamar al mtodo GetResourceStream de la clase Application,
pasando un pack URI que identifique el archivo de recursos deseado. GetResourceStream devuelve un objeto
StreamResourceInfo, que expone el archivo de recursos como un objeto Stream y describe su tipo de
contenido.
Como ejemplo, en el cdigo siguiente se muestra cmo utilizar GetResourceStream para cargar un archivo de
recursos Page y establecerlo como contenido de un control Frame (pageFrame):
// Navigate to xaml page
Uri uri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetResourceStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
Aunque al llamar a GetResourceStream se obtiene acceso a Stream, debe realizar el trabajo adicional de
convertirlo en el tipo de la propiedad con la que lo establecer. Como alternativa, puede dejar que WPF se
ocupe de abrir y convertir el objeto Stream cargando un archivo de recursos directamente en la propiedad de
un tipo mediante cdigo.
En el ejemplo siguiente, se muestra cmo se carga un control Page directamente en un control Frame
(pageFrame) mediante cdigo.
Uri pageUri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
El ejemplo siguiente es el equivalente en marcado del ejemplo anterior.
<Frame Name="pageFrame" Source="PageResourceFile.xaml" />
Archivos de cdigo de aplicacin como archivos de recursos
Se puede hacer referencia a un conjunto especial de archivos de cdigo de aplicacin de WPF utilizando pack
URIs, incluidos documentos dinmicos, ventanas, pginas y diccionarios de recursos. Por ejemplo, puede
Pag 56 de 445
Pag 57 de 445
Copy always (es lo mismo que Always) y Copy if newer (es lo mismo que PreserveNewest).
Cuando se genera el proyecto, se compila un atributo AssemblyAssociatedContentFileAttribute en los metadatos
del ensamblado para cada archivo de contenido.
[assembly: AssemblyAssociatedContentFile("ContentFile.xaml")]
El valor de AssemblyAssociatedContentFileAttribute implica la ruta de acceso al archivo de contenido con
respecto a su posicin en el proyecto. Por ejemplo, si un archivo de contenido se encontrara en una subcarpeta
del
proyecto,
la
informacin
adicional
de
ruta
de
acceso
se
incorporara
en
el
valor
de
AssemblyAssociatedContentFileAttribute.
[assembly: AssemblyAssociatedContentFile("Resources/ContentFile.xaml")]
El valor de AssemblyAssociatedContentFileAttribute es tambin el valor de la ruta de acceso al archivo de
contenido en la carpeta de resultados de la compilacin.
Utilizar archivos de contenido
Para cargar un archivo de contenido, puede llamar al mtodo GetContentStream de la clase Application,
pasando un pack URI que identifique el archivo de recursos deseado. GetContentStream devuelve un objeto
StreamResourceInfo, que expone el archivo de contenido como un objeto Stream y describe su tipo de
contenido.
Como ejemplo, en el cdigo siguiente se muestra cmo utilizar GetContentStream para cargar un archivo de
contenido Page y establecerlo como contenido de un control Frame (pageFrame).
// Navigate to xaml page
Uri uri = new Uri("/PageContentFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetContentStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
Aunque al llamar a GetContentStream se obtiene acceso a Stream, debe realizar el trabajo adicional de
convertirlo en el tipo de la propiedad con la que lo establecer. Como alternativa, puede dejar que WPF se
ocupe de abrir y convertir el objeto Stream cargando un archivo de recursos directamente en la propiedad de
un tipo mediante cdigo.
En el ejemplo siguiente, se muestra cmo se carga un control Page directamente en un control Frame
(pageFrame) mediante cdigo.
Uri pageUri = new Uri("/PageContentFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
El ejemplo siguiente es el equivalente en marcado del ejemplo anterior.
<Frame Name="pageFrame" Source="PageContentFile.xaml" />
Archivos de sitio de origen
Los archivos de recursos tienen una relacin explcita con los ensamblados junto a los que se distribuyen, segn
lo definido en AssemblyAssociatedContentFileAttribute. No obstante, habr ocasiones en las que quiz desee
establecer una relacin implcita o inexistente entre un ensamblado y un archivo de datos de aplicacin, por
ejemplo cuando:
La aplicacin utilice archivos de datos grandes, como los de audio y vdeo, y desee que los usuarios los
descarguen slo si as lo eligen.
Es posible cargar estos tipos de archivo utilizando esquemas de URI tradicionales, como los esquemas file:/// y
http://.
<Image Source="file:///C:/DataFile.bmp" />
<Image Source="http://www.datafilewebsite.com/DataFile.bmp" />
Sin embargo, los esquemas file:/// y http:// requieren que la aplicacin sea de plena confianza. Si la aplicacin
es una aplicacin Aplicacin del explorador XAML (XBAP) iniciada desde Internet o desde una intranet y solicita
solamente el conjunto de permisos que se permiten para las aplicaciones iniciadas desde esas ubicaciones, los
Pag 58 de 445
Pag 59 de 445
Especificando la interfaz de usuario (UI) que se va a mostrar cuando se inicie una aplicacin por
primera vez.
Cargando imgenes.
Navegando a pginas.
Cargando archivos de datos no ejecutables.
Adems, se pueden usar URIs para identificar y cargar archivos desde diversas ubicaciones, como las que
figuran a continuacin:
El ensamblado actual.
Un ensamblado al que se hace referencia.
Una ubicacin relativa a un ensamblado.
El sitio de origen de la aplicacin.
Para proporcionar un mecanismo coherente para identificar y cargar estos tipos de archivo desde estas
ubicaciones, WPF aprovecha la extensibilidad del esquema de pack URI. En este tema se proporciona
informacin general sobre el esquema, se describe cmo construir pack URIs para diversos escenarios, se
explican los URIs absolutos y relativos y la resolucin de URI antes de mostrar cmo utilizar los pack URIs tanto
desde el marcado como desde el cdigo.
Esquema de pack URI
El esquema de pack URI se utiliza en la especificacin de Open Packaging Conventions (OPC), que describe un
modelo para organizar e identificar contenido. Los elementos clave de este modelo son los paquetes y las
partes, donde un paquete es un contenedor lgico para una o varias partes lgicas. La figura siguiente ilustra
este concepto.
Para identificar las partes, la especificacin de OPC aprovecha la extensibilidad de RFC 2396 (Identificadores
uniformes de recursos (URI): sintaxis genrica) para definir el esquema de pack URI.
El esquema especificado por un URI se define por su prefijo; http, ftp y file son ejemplos conocidos. El esquema
de pack URI utiliza "pack" como esquema y tiene dos componentes: la autoridad y la ruta de acceso. A
continuacin figura el formato de un pack URI.
pack://autoridad/ruta de acceso
Pag 60 de 445
Los paquetes y las partes son anlogos a las aplicaciones y los archivos, puesto que una aplicacin (paquete)
puede incluir uno o varios archivos (partes), como los siguientes:
Para obtener acceso a estos tipos de archivo, WPF admite dos autoridades: application:/// y siteoforigin:///. La
autoridad application:/// identifica los archivos de datos de aplicacin que se conocen en tiempo de
compilacin, incluidos los archivos de recursos y de contenido. La autoridad siteoforigin:/// identifica los
archivos de sitio de origen. El mbito de cada autoridad se muestra en la figura siguiente.
Nota:
El componente de autoridad de un pack URI es un URI incrustado que apunta a un paquete y debe
ajustarse a RFC 2396. Adems, el carcter "/" debe sustituirse por el carcter "," y los caracteres
reservados tales como "%" y "?" deben incluirse en secuencias de escape. Vea la especificacin de OPC
para obtener informacin detallada.
En las secciones siguientes se explica cmo construir pack URIs utilizando estas dos autoridades junto con las
rutas de acceso adecuadas para identificar los archivos de recursos, de contenido y de sitio de origen.
Pack URI de archivos de recursos
Los archivos de recursos se configuran como elementos Resource de MSBuild y se compilan en ensamblados.
WPF admite la construccin de pack URIs que se pueden utilizar para identificar los archivos de recursos
compilados en el ensamblado local o compilados en un ensamblado al que se hace referencia desde el
ensamblado local.
Archivo de recursos del ensamblado local
El pack URI para un archivo de recursos compilado en el ensamblado local utiliza la siguiente autoridad y ruta
de acceso:
Autoridad: application:///.
Ruta de acceso: nombre del archivo de recursos, incluida su ruta de acceso relativa a la carpeta raz
del proyecto de ensamblado local.
Pag 61 de 445
Autoridad: application:///.
Ruta de acceso: nombre de un archivo de recursos compilado en un ensamblado al que se hace
referencia. La ruta de acceso debe tener el formato siguiente:
nombreCortoDeEnsamblado[;Versin][;clavePblica];component/rutaDeAcceso
;clavePblica [opcional]: clave pblica utilizada para firmar el ensamblado al que se hace
referencia. Se utiliza cuando hay cargados dos o ms ensamblados a los que se hace referencia
con el mismo nombre corto.
En el ejemplo siguiente se muestra el pack URI para un archivo de recursos XAML que se encuentra en la
carpeta raz del proyecto de ensamblado al que se hace referencia.
pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml
En el ejemplo siguiente se muestra el pack URI para un archivo de recursos XAML que se encuentra en una
subcarpeta de la carpeta del proyecto de ensamblado al que se hace referencia.
pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml
En el ejemplo siguiente se muestra el pack URI para un archivo de recursos XAML que se encuentra en la
carpeta raz de un proyecto de ensamblado especfico de la versin al que se hace referencia.
pack://application:,,,/ReferencedAssembly;v1.0.0.1;component/ResourceFile.xaml
Observe que la sintaxis del pack URI para los archivos de recursos de ensamblado a los que se hace referencia
solamente se puede utilizar con la autoridad application:///. Por ejemplo, no se admite lo siguiente en WPF.
pack://siteoforigin:,,,/SomeAssembly;component/ResourceFile.xaml
Pack URI de archivo de contenido
El pack URI para un archivo de contenido utiliza la siguiente autoridad y ruta de acceso:
Autoridad: application:///.
Ruta de acceso: nombre del archivo de contenido, incluida su ruta de acceso relativa a la ubicacin del
sistema de archivos del ensamblado ejecutable principal de la aplicacin.
En el ejemplo siguiente se muestra el pack URI para un archivo de contenido XAML, ubicado en la misma
carpeta que el ensamblado ejecutable.
pack://application:,,,/ContentFile.xaml
Pag 62 de 445
Autoridad: siteoforigin:///.
Ruta de acceso: nombre del archivo de sitio de origen, incluida su ruta de acceso relativa a la
ubicacin desde la que se inici el ensamblado ejecutable.
En el ejemplo siguiente se muestra el pack URI para un archivo de sitio de origen XAML, almacenado en la
ubicacin desde la que se inicia el ensamblado ejecutable.
pack://siteoforigin:,,,/SiteOfOriginFile.xaml
En el ejemplo siguiente se muestra el pack URI para un archivo de sitio de origen XAML, almacenado en una
subcarpeta relativa a la ubicacin desde la que se inicia el ensamblado ejecutable de la aplicacin.
pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml
Archivos de paginacin
Los archivos XAML configurados como elementos Page de MSBuild se compilan en ensamblados del mismo
modo que los archivos de recursos. Por consiguiente, los elementos Page de MSBuild se pueden identificar
mediante los pack URIs para los archivos de recursos.
Los tipos de archivo XAML que se configuran habitualmente como elementos Page de MSBuild tienen uno de los
siguientes elementos como elemento raz:
System.Windows.Window
System.Windows.Controls.Page
System.Windows.Navigation.PageFunction<(Of <(T>)>)
System.Windows.ResourceDictionary
System.Windows.Documents.FlowDocument
System.Windows.Controls.UserControl
Pag 63 de 445
Sondear
los
metadatos
del
ensamblado
para
buscar
un
atributo
3.
4.
Si se encuentra un archivo de recursos que coincida con el pack URI, la ruta de acceso del pack URI
hace referencia a un archivo de recursos.
5.
La resolucin de URI no se aplica a los URIs que hacen referencia a los siguientes archivos:
Archivos de contenido en ensamblados a los que se hace referencia: WPF no admite estos tipos de
archivo.
Archivos incrustados en ensamblados a los que se hace referencia: los URIs que los identifican son
nicos porque incluyen tanto el nombre del ensamblado al que se hace referencia como el sufijo
;component.
Archivos de sitio de origen: los URIs que los identifican son nicos porque son los nicos archivos que
se pueden identificar mediante pack URIs que contienen la autoridad siteoforigin:///.
Una simplificacin que permite la resolucin de pack URI es que el cdigo sea independiente, hasta cierto
punto, de la ubicacin de los archivos de recursos y de contenido. Por ejemplo, si tiene un archivo de recursos
en el ensamblado local que se ha reconfigurado para que sea un archivo de contenido, el pack URI para el
recurso continuar siendo el mismo, al igual que el cdigo que utiliza el pack URI.
Programar con pack URI
Pag 64 de 445
Application.StartupUri
Frame.Source
NavigationWindow.Source
Hyperlink.NavigateUri
Window.Icon
Image.Source
Estas propiedades se pueden establecer tanto desde marcado como desde cdigo. En esta seccin se muestran
las construcciones bsicas para ambos y, a continuacin, se muestra ejemplos de escenarios comunes.
Utilizar pack URI en el marcado
Un pack URI se especifica en el marcado estableciendo el elemento de un atributo con el pack URI. Por
ejemplo:
<element attribute="pack://application:,,,/File.xaml" />
En la tabla 1 se muestran los diversos pack URIs absolutos que se pueden especificar en el marcado.
Tabla 1: pack URI absolutos en el marcado
Archivo
Archivo de recursos:
ensamblado local
"pack://application:,,,/ResourceFile.xaml"
Archivo de recursos en
subcarpeta: ensamblado local
"pack://application:,,,/Subfolder/ResourceFile.xaml"
Archivo de recursos:
ensamblado al que se hace
referencia
"pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml"
Archivo de recursos en
subcarpeta del ensamblado al
que se hace referencia
"pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"
Archivo de recursos en el
ensamblado al que se hace
referencia con versin
"pack://application:,,,/ReferencedAssembly;v1.0.0.0;component/ResourceFile.xaml"
Archivo de contenido
"pack://application:,,,/ContentFile.xaml"
Archivo de contenido en
subcarpeta
"pack://application:,,,/Subfolder/ContentFile.xaml"
"pack://siteoforigin:,,,/SOOFile.xaml"
"pack://siteoforigin:,,,/Subfolder/SOOFile.xaml"
En la tabla 2 se muestran los diversos pack URIs relativos que se pueden especificar en el marcado.
Tabla 2: pack URI relativos en el marcado
Archivo
"/ResourceFile.xaml"
"/Subfolder/ResourceFile.xaml"
"/ReferencedAssembly;component/ResourceFile.xaml"
Pag 65 de 445
"/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"
Archivo de contenido
"/ContentFile.xaml"
"/Subfolder/ContentFile.xaml"
Archivo de recursos:
ensamblado local
Archivo de recursos
en subcarpeta:
ensamblado local
Archivo de recursos:
ensamblado al que se
hace referencia
Archivo de recursos
en subcarpeta del
ensamblado al que se
hace referencia
Archivo de recursos
en el ensamblado al
que se hace
referencia con versin
Archivo de contenido
Archivo de contenido
en subcarpeta
Archivo de sitio de
origen
Archivo de sitio de
origen en subcarpeta
UriKind.Absolute);
Uri("pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml",
UriKind.Absolute);
Uri("pack://application:,,,/ReferencedAssembly;v1.0.0.0;component/ResourceFile.xaml",
UriKind.Absolute);
Pag 66 de 445
Archivo de recursos en
subcarpeta: ensamblado local
Archivo de recursos en
subcarpeta: ensamblado al que se
hace referencia
UriKind.Relative);
Uri("/ReferencedAssembly;component/Subfolder/ResourceFile.xaml",
UriKind.Relative);
Archivo de contenido
Archivo de contenido en
subcarpeta
Pag 67 de 445
Pag 68 de 445
Pag 69 de 445
Pag 70 de 445
}
catch (FileNotFoundException ex)
{
// Handle when file is not found in isolated storage:
// * When the first application session
// * When file has been deleted
}
}
private void App_Exit(object sender, ExitEventArgs e)
{
// Persist application-scope property to isolated storage
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForDomain();
using (IsolatedStorageFileStream stream = new _
IsolatedStorageFileStream(filename, FileMode.Create, storage))
using (StreamWriter writer = new StreamWriter(stream))
{
// Persist each application-scope property individually
foreach (string key in this.Properties.Keys)
{
writer.WriteLine("{0},{1}", key, this.Properties[key]);
}
}
}
}
Pag 71 de 445
Una ventana est dividida en dos reas: el rea de no cliente y rea cliente.
El rea de no cliente de una ventana se implementa mediante WPF e incluye las partes de una ventana que son
comunes a la mayora de las ventanas, incluidas las siguientes:
Borde.
Barra de ttulo.
Icono.
Pag 72 de 445
El rea cliente de una ventana es el rea dentro del rea de no cliente de una ventana y es utilizada por los
programadores para agregar contenido especfico de la aplicacin, tal como barras de mens, barras de
herramientas y controles.
En WPF, las ventanas se encapsulan en la clase Window, que se utiliza para hacer lo siguiente:
En el archivo de cdigo subyacente, la clase debe ser una clase partial con el mismo nombre que el
que especific el atributo x:Class en el marcado, y debe derivarse de Window. Esto permite que el
archivo de cdigo subyacente se asocie a la clase partial que se genera para el archivo de marcado
cuando se crea la aplicacin.
En el archivo de cdigo subyacente, la clase Window debe implementar un constructor que llame al
mtodo InitializeComponent. InitializeComponent se implementa mediante la clase partial generada
Pag 73 de 445
Pag 74 de 445
}
En este ejemplo, se crea una instancia de MarkupAndCodeBehindWindow cuando se inicia la aplicacin, lo que
ocurre cuando se produce el evento Startup.
Cuando se crea una instancia de una ventana, automticamente se agrega una referencia a la ventana a la lista
de ventanas administrada por el objeto Application. Adems, Application establece la primera ventana de la que
se crea una instancia, de forma predeterminada, como la ventana principal de la aplicacin.
La ventana se abre finalmente llamando al mtodo Show; el resultado se muestra en la figura siguiente.
Una ventana que se abre llamando a Show es una ventana no modal, lo que significa que la aplicacin funciona
en un modo que permite a los usuarios activar otras ventanas en la misma aplicacin.
Nota:
Para abrir tales ventanas como cuadros de dilogo, modalmente, se llama a ShowDialog.
Cuando se llama a Show, una ventana realiza antes de mostrarse un trabajo de inicializacin que establece la
infraestructura necesaria para recibir la entrada del usuario. Cuando se inicializa la ventana, se provoca el
evento SourceInitialized y se muestra la ventana.
Como mtodo abreviado, se puede establecer StartupUri para especificar la primera ventana que se abre
automticamente cuando se inicia una aplicacin.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="PlainWindow.xaml" />
Cuando se inicia la aplicacin, la ventana especificada por el valor de StartupUri se abre de forma no modal;
internamente, la ventana se abre llamando a su mtodo Show.
Propiedad de la ventana
Una ventana que se abre utilizando el mtodo Show no tiene una relacin implcita con la ventana que la cre;
los usuarios pueden interactuar con cualquier ventana independientemente de las dems, lo que significa que
cualquier ventana puede hacer lo siguiente:
Cubrir las dems (a menos que una de las ventanas tenga su propiedad Topmost establecida en true).
Minimizarse, maximizarse y restaurarse sin afectar a las dems.
Algunas ventanas requieren una relacin con la ventana que las abre. Por ejemplo, una aplicacin Entorno de
desarrollo integrado (IDE) puede abrir ventanas de propiedades y ventanas de herramientas cuyo
comportamiento tpico es cubrir la ventana que las crea. Adems, tales ventanas siempre se deben cerrar,
minimizar, maximizar y restaurar de acuerdo con la ventana que las cre. Este tipo de relacin se puede
establecer haciendo que una ventana posea otra y se logra estableciendo la propiedad Owner de la ventana
poseda con una referencia a la ventana propietaria. Esto se muestra en el ejemplo siguiente.
// Create a window and make this window its owner
Window ownedWindow = new Window();
ownedWindow.Owner = this;
ownedWindow.Show();
Una vez establecida la propiedad:
La ventana propietaria puede detectar todas las ventanas que posee inspeccionando el valor de su
propiedad OwnedWindows.
Pag 75 de 445
Pag 76 de 445
Nota:
Puede administrar la activacin del mbito de la aplicacin mediante los eventos Application.Activated y
Application.Deactivated.
Cerrar una ventana
La duracin de una ventana empieza a acabarse cuando un usuario la cierra. Una ventana se puede cerrar
utilizando los elementos del rea de no cliente, incluidos los siguientes:
Puede proporcionar mecanismos adicionales al rea cliente para cerrar una ventana; algunos de los ms
comunes son los siguientes:
Un elemento Salir en el men Archivo, normalmente para las ventanas principales de la aplicacin.
Un elemento Cerrar en el men Archivo, normalmente en una ventana secundaria de la aplicacin.
Un botn Cancelar, normalmente en un cuadro de dilogo modal.
Un botn Cerrar, normalmente en un cuadro de dilogo no modal.
Para cerrar una ventana en respuesta a uno de estos mecanismos personalizados, debe llamar al mtodo Close.
En el ejemplo siguiente se implementa la capacidad de cerrar una ventana eligiendo Salir en el men Archivo.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.WindowWithFileExit">
<Menu>
<MenuItem Header="_File">
<MenuItem Header="E_xit" Click="fileExitMenuItem_Click" />
</MenuItem>
</Menu>
</Window>
using System.Windows; // window, RoutedEventArgs
namespace SDKSample
{
public partial class WindowWithFileExit : System.Windows.Window
{
public WindowWithFileExit()
{
InitializeComponent();
}
void fileExitMenuItem_Click(object sender, RoutedEventArgs e)
{
// Close this window
this.Close();
}
}
}
Cuando una ventana se cierra, provoca dos eventos: Closing y Closed.
Closing se provoca antes de que la ventana se cierre y proporciona un mecanismo para evitar el cierre de la
ventana. Una razn comn para evitar el cierre de la ventana es que el contenido de la ventana contenga datos
modificados. En esta situacin, se puede administrar el evento Closing para determinar si los datos se han
modificado y, en ese caso, preguntar al usuario si desea continuar cerrando la ventana sin guardar los datos o
si desea cancelar el cierre de la ventana. En el ejemplo siguiente se muestran los aspectos clave de la
administracin de Closing.
using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // window
namespace CSharp
{
public partial class DataWindow : Window
{
// Is data dirty
bool isDataDirty = false;
...
void DataWindow_Closing(object sender, CancelEventArgs e)
{
MessageBox.Show("Closing called");
Pag 77 de 445
}
Al controlador del evento Closing se le pasa un objeto CancelEventArgs, que implementa la propiedad
BooleanCancel que se establece en true para evitar que una ventana se cierre.
Si no se administra Closing, o se administra pero no se cancela, la ventana se cierra. El evento Closed se
produce inmediatamente antes de que una ventana se cierre realmente. En este punto, no se puede evitar que
la ventana se cierre.
Nota:
Una aplicacin se puede configurar para que se cierre automticamente cuando se cierre la ventana de la
aplicacin principal o cuando se cierre la ltima ventana.
Aunque una ventana se puede cerrar explcitamente a travs de los mecanismos proporcionados en las reas
cliente y no cliente, una ventana tambin se puede cerrar implcitamente como resultado del comportamiento
de otras partes de la aplicacin o de Windows, incluido lo siguiente:
Nota:
Una ventana no se puede volver a abrir una vez cerrada.
Eventos de duracin de ventana
La ilustracin siguiente muestra la secuencia de eventos principales en la duracin de una ventana.
Ubicacin de la ventana
Mientras una ventana est abierta, tiene una ubicacin en las dimensiones xe y respecto al escritorio. Esta
ubicacin se puede determinar inspeccionando las propiedades Left y Top, respectivamente. Puede establecer
estas propiedades para cambiar la ubicacin de la ventana.
Tambin puede especificar la ubicacin inicial de un objeto Window la primera vez que aparece estableciendo la
propiedad WindowStartupLocation en uno de los siguientes valores de la enumeracin WindowStartupLocation:
Manual (predeterminado)
CenterScreen
CenterOwner
Pag 78 de 445
Height. Ajustar al alto del contenido, que tiene el mismo efecto que establecer MinHeight y MaxHeight
en el alto del contenido.
WidthAndHeight. Ajustar al ancho y al alto del contenido, que tiene el mismo efecto que establecer
tanto MinHeight como MaxHeight en el alto del contenido, y establecer tanto MinWidth como MaxWidth
en el ancho del contenido.
En el cdigo siguiente se muestra una ventana cuyo tamao se ajusta automticamente a su contenido, tanto
vertical como horizontalmente, cuando se muestra por primera vez.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
SizeToContent="WidthAndHeight">
...
Pag 79 de 445
FrameworkElement..MinHeight >
2.
FrameworkElement.MaxHeight >
3.
SizeToContent.Height/SizeToContent.WidthAndHeight >
4.
FrameworkElement.Height
FrameworkElement.MinWidth >
2.
FrameworkElement.MaxWidth >
3.
SizeToContent.Width/SizeToContent.WidthAndHeight >
4.
FrameworkElement.Width
El orden de prioridad tambin puede determinar el tamao de una ventana cuando se maximiza, lo que se
administra con la propiedad WindowState.
Estado de la ventana
Durante la duracin de una ventana de tamao variable, puede tener tres estados: normal, minimizado y
maximizado. Una ventana con un estado normal es el estado predeterminado de una ventana. Una ventana con
este estado permite al usuario moverla y cambiar su tamao utilizando los controladores de tamao o el borde,
si es de tamao variable.
Una ventana con el estado minimizado se contrae a su botn de la barra de tareas si ShowInTaskbar est
establecido en true; de lo contrario, se contrae al mnimo tamao posible y se reubica en la esquina inferior
izquierda del escritorio. Ningn tipo de ventana minimizada puede cambiar su tamao mediante el borde ni
controladores de tamao, aunque una ventana minimizada que no se muestre en la barra de tareas puede
arrastrarse por el escritorio.
Una ventana con un estado maximizado se expande a su tamao mximo, que solamente puede ser tan grande
como dicten sus propiedades MaxWidth, MaxHeight y SizeToContent. Como ocurre con una ventana
minimizada, no se puede cambiar el tamao de una ventana maximizada utilizando un controlador de tamao
ni arrastrando el borde.
El estado de una ventana se puede configurar estableciendo su propiedad WindowState, que puede tener uno
de los siguientes valores de la enumeracin WindowState:
Normal (predeterminado)
Maximized
Minimized
En el ejemplo siguiente se muestra cmo crear una ventana que se muestra como maximizada al abrirse.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowState="Maximized">
...
</Window>
En general, es recomendable establecer WindowState para configurar el estado inicial de una ventana. Una vez
mostrada una ventana de tamao variable, los usuarios pueden presionar los botones de minimizar, maximizar
y restablecer de la barra de ttulo de la ventana para cambiar el estado de la ventana.
Aspecto de la ventana
Pag 80 de 445
NoResize
CanMinimize
CanResize (predeterminado)
CanResizeWithGrip
Como ocurre con WindowStyle, es improbable que el modo de cambio de tamao de una ventana cambie
durante su duracin, los que significa que probablemente se establecer desde el marcado XAML.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
ResizeMode="CanResizeWithGrip">
...
</Window>
Observe que puede detectar si una ventana est maximizada, minimizada o restaurada inspeccionando la
propiedad WindowState.
Estilo de ventana
El borde que se expone desde el rea de no cliente de una ventana es adecuado para la mayora de las
aplicaciones. Sin embargo, hay circunstancias en las que se necesitan diferentes tipos de borde, o no se
necesita ningn borde en absoluto, segn el tipo de ventana.
Para controlar qu tipo de borde obtiene una ventana, establezca su propiedad WindowStyle con uno de los
siguientes valores de la enumeracin WindowStyle:
None
SingleBorderWindow (predeterminado)
ThreeDBorderWindow
ToolWindow
Pag 81 de 445
Puede establecer WindowStyle mediante marcado XAML o mediante cdigo; dado que es improbable que
cambie durante la duracin de una ventana, lo ms probable es que lo configure utilizando el marcado XAML.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowStyle="ToolWindow">
...
</Window>
Estilo de ventana no rectangular
Tambin hay situaciones en las que los estilos de borde que permite WindowStyle no sern suficientes. Por
ejemplo, quiz desee crear una aplicacin con un borde no rectangular, como el que utiliza Microsoft Windows
Media Player.
Por ejemplo, considere la ventana de burbuja de voz que se muestra en la figura siguiente.
Este tipo de ventana se puede crear estableciendo la propiedad WindowStyle en None y utilizando la
compatibilidad especial de Window para la transparencia.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent">
...
</Window>
Esta combinacin de valores indica a la ventana que debe representarse completamente transparente. En este
estado, las opciones grficas del rea de no cliente de la ventana (el men Cerrar, los botones Minimizar,
Maximizar y Restaurar, etc.) no se pueden utilizar. Por consiguiente, necesita proporcionar opciones propias.
Presencia de la barra de tareas
El aspecto predeterminado de una ventana incluye un botn de barra de tareas, como el que se muestra en la
figura siguiente.
Algunos tipos de ventana no tienen botn de barra de tareas, como los cuadros de mensaje y los cuadros de
dilogo. Puede controlar si se muestra el botn de barra de tareas para una ventana estableciendo la propiedad
ShowInTaskbar (true de forma predeterminada).
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
ShowInTaskbar="False">
...
</Window>
Consideraciones de seguridad
Pag 82 de 445
Estos tipos de ventanas se conocen como cuadros de dilogo y hay dos tipos: modales y no modales.
Los cuadros de dilogo modales los muestras las funciones cuando necesitan datos adicionales de los usuarios
para continuar. Dado que la funcin depende del cuadro de dilogo modal para recopilar los datos, el cuadro de
dilogo modal tambin impide que un usuario active otras ventanas de la aplicacin mientras permanece
abierto. En la mayora de los casos, los cuadros de dilogo modales permiten a los usuarios sealar que han
terminado con el cuadro de dilogo modal presionando un botn Aceptar o Cancelar. Al presionar el botn
Aceptar se indica que el usuario ha introducido los datos y desea que la funcin contine su proceso con esos
datos. Presionar el botn Cancelar indica que el usuario desea detener la ejecucin de la funcin. Los ejemplos
ms comunes de cuadros de dilogo modales se muestran para abrir, guardar e imprimir datos.
Un cuadro de dilogo no modal, por otra parte, no impide que el usuario active otras ventanas mientras est
abierto. Por ejemplo, si un usuario desea buscar apariciones de una palabra determinada en un documento,
una ventana principal abrir habitualmente un cuadro de dilogo para preguntar al usuario qu palabra est
buscando. Dado que la bsqueda de una palabra no impide que un usuario edite el documento, no obstante, no
es necesario que el cuadro de dilogo sea modal. Un cuadro de dilogo no modal proporciona al menos un
botn Cerrar para cerrar el cuadro de dilogo y puede proporcionar botones adicionales para ejecutar funciones
concretas, como un botn Buscar siguiente para buscar la palabra siguiente que coincida con los criterios de
una bsqueda de palabra.
Windows Presentation Foundation (WPF) permite crear varios tipos de cuadros de dilogo, incluidos cuadros de
mensaje, cuadros de dilogo comunes y cuadros de dilogo personalizados.
Cuadros de mensaje
Un cuadro de mensaje es un cuadro de dilogo que se puede utilizar para mostrar informacin textual y
permitirles que los usuarios tomen decisiones con botones. La figura siguiente muestra un cuadro de mensaje
Pag 83 de 445
Para crear un cuadro de mensaje, utilice la clase MessageBox. MessageBox permite configurar el texto, el ttulo,
el icono y los botones del cuadro de mensaje, utilizando cdigo como el siguiente.
// Configure the message box to be displayed
string messageBoxText = "Do you want to save changes?";
string caption = "Word Processor";
MessageBoxButton button = MessageBoxButton.YesNoCancel;
MessageBoxImage icon = MessageBoxImage.Warning;
Para mostrar un cuadro de mensaje, llame al mtodo static Show, como se muestra en el cdigo siguiente.
Cuando el cdigo que muestra un cuadro de mensaje necesite detectar y procesar la decisin del usuario (qu
botn se presion), el cdigo puede inspeccionar el resultado del cuadro de mensaje, como se muestra en el
cdigo siguiente.
// Display message box
MessageBoxResult result = MessageBox.Show(messageBoxText, caption, button, icon);
// Process message box results
switch (result)
{
case MessageBoxResult.Yes:
// User pressed Yes button
// ...
break;
case MessageBoxResult.No:
// User pressed No button
// ...
break;
case MessageBoxResult.Cancel:
// User pressed Cancel button
// ...
break;
}
Aunque MessageBox puede proporcionar una experiencia simple de usuario de cuadro de dilogo, la ventaja de
utilizar MessageBox es que se trata del nico tipo de ventana que pueden mostrar las aplicaciones que se
ejecutan dentro de un recinto de seguridad confiable parcial, tal como Aplicaciones del explorador XAML
(XBAPs).
La mayora de los cuadros de dilogo muestran y recopilan datos ms complejos que el resultado de un cuadro
de mensaje, incluidos texto, selecciones (casillas), selecciones mutuamente excluyentes (botones de opcin) y
selecciones de lista (cuadros de lista, cuadros combinados, cuadros de lista desplegables). Para stos, Windows
Presentation Foundation (WPF) proporciona varios cuadros de dilogo comunes y permite crear cuadros de
dilogo propios, aunque el uso de cualquiera de ellos se limita a aplicaciones que se ejecuten con plena
confianza.
Cuadros de dilogo comunes
Windows implementa diversos cuadros de dilogo reutilizables que son comunes para todas las aplicaciones,
incluidos cuadros de dilogo para abrir archivos, guardar archivos e imprimir. Puesto que es el sistema
operativo el que implementa estos cuadros de dilogo, se pueden compartir entre todas las aplicaciones que se
ejecutan en el sistema operativo, los que contribuye a la coherencia de la experiencia del usuario; cuando los
usuarios estn familiarizados con el uso de un cuadro de dilogo proporcionado por el sistema operativo en una
aplicacin, no necesitan obtener informacin sobre cmo utilizar ese cuadro de dilogo en otras aplicaciones.
Dado que estos cuadros de dilogo estn disponibles para todas las aplicaciones y que ayudan a proporcionar
una experiencia de usuario coherente, se conocen como cuadros de dilogo comunes.
Pag 84 de 445
Pag 85 de 445
El cuadro de dilogo comn de impresin de archivos se implementa como la clase PrintDialog y se encuentra
en el espacio de nombres System.Windows.Controls. El cdigo siguiente muestra cmo crear, configurar y
mostrar uno.
Cuadros de dilogo personalizados
Pag 86 de 445
Mostrar un botn Cancelar en el que los usuarios hagan clic para cerrar el cuadro de dilogo y hacer
que la funcin detenga el proceso.
Es recomendable configurar la accin de presionar la tecla ESC como un mtodo abreviado de teclado
que haga que se presione el botn Cancelar. Esto se logra estableciendo la propiedad IsCancel del
botn Cancelar en true.
Pag 87 de 445
Pag 88 de 445
Desde la perspectiva especfica del dominio, la validacin de datos impide que el cdigo procese datos
errneos, lo que podra iniciar excepciones.
Desde la perspectiva de un usuario, un cuadro de dilogo puede ayudar a los usuarios mostrndoles
qu datos de los introducidos no son vlidos.
Desde la perspectiva del rendimiento, la validacin de datos en una aplicacin de varios niveles puede
reducir el nmero de viajes de ida y vuelta entre los niveles de cliente y de aplicacin, en particular
cuando la aplicacin se compone de servicios web o bases de datos basadas en servidor.
Para validar un control enlazado en WPF, debe definir una regla de validacin y asociarla al enlace. Una regla de
validacin es una clase personalizada derivada de ValidationRule. El ejemplo siguiente muestra una regla de
validacin, MarginValidationRule, que comprueba que un valor enlazado es Double y est dentro de un intervalo
especificado.
Imports System.Globalization
Imports System.Windows.Controls
Namespace SDKSample
Public Class MarginValidationRule
Inherits ValidationRule
Private _maxMargin As Double
Private _minMargin As Double
Public Property MaxMargin() As Double
Get
Return Me._maxMargin
End Get
Set(ByVal value As Double)
Me._maxMargin = value
End Set
End Property
Public Property MinMargin() As Double
Get
Return Me._minMargin
End Get
Set(ByVal value As Double)
Me._minMargin = value
End Set
End Property
Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As
CultureInfo) As ValidationResult
Dim margin As Double
' Is a number?
If Not Double.TryParse(CStr(value), margin) Then
Return New ValidationResult(False, "Not a number.")
End If
' Is in range?
If ((margin < Me.MinMargin) OrElse (margin > Me.MaxMargin)) Then
Dim msg As String = String.Format("Margin must be between {0} and {1}.",
Me.MinMargin, Me.MaxMargin)
Return New ValidationResult(False, msg)
End If
' Number is valid
Return New ValidationResult(True, Nothing)
End Function
End Class
End Namespace
En este cdigo, la lgica de validacin de una regla de validacin se implementa invalidando el mtodo Validate,
que valida los datos y devuelve el objeto ValidationResult correspondiente.
Para asociar la regla de validacin al control enlazado, utilice el marcado siguiente.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MarginsDialogBox"
xmlns:local="clr-namespace:SDKSample"
Title="Margins"
Height="190"
Width="300"
MinHeight="10"
MinWidth="300"
ResizeMode="CanResizeWithGrip"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner"
FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">
<Grid>
...
<Label Grid.Column="0" Grid.Row="0">Left Margin:</Label>
<TextBox Name="leftMarginTextBox" Grid.Column="1" Grid.Row="0">
<TextBox.Text>
<Binding Path="Left" UpdateSourceTrigger="PropertyChanged">
Pag 89 de 445
WPF no restringe a un usuario al control no vlido hasta que haya introducido datos vlidos. sta es una buena
prctica para un cuadro de dilogo; un usuario debe poder navegar libremente por los controles de un cuadro
de dilogo tanto si los datos son vlidos como si no. Sin embargo, esto significa que un usuario puede
introducir datos no vlidos y presionar el Aceptar botn. Por esta razn, el cdigo necesita adems validar
todos los controles del cuadro de dilogo cuando se presione el botn Aceptar, controlando el evento Click.
Imports System.Windows ' Window, RoutedEventArgs, IInputElement, DependencyObject
Imports System.Windows.Controls ' Validation
Imports System.Windows.Input ' Keyboard
Namespace SDKSample
Public Class MarginsDialogBox
Inherits Window
Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Don't accept the dialog box if there is invalid data
If Not Me.IsValid(Me) Then Return
End Sub
' Validate all dependency objects in a window
Private Function IsValid(ByVal node As DependencyObject) As Boolean
' Check if dependency object was passed and if dependency object is valid.
' NOTE: Validation.GetHasError works for controls that have validation rules attached
If ((Not node Is Nothing) AndAlso Validation.GetHasError(node)) Then
' If the dependency object is invalid, and it can receive the focus,
' set the focus
If TypeOf node Is IInputElement Then
Keyboard.Focus(DirectCast(node, IInputElement))
End If
Return False
End If
' If this dependency object is valid, check all child dependency objects
Dim subnode As Object
For Each subnode In LogicalTreeHelper.GetChildren(node)
If (TypeOf subnode Is DependencyObject AndAlso Not
Me.IsValid(DirectCast(subnode, DependencyObject))) Then
' If a child dependency object is invalid, return false immediately,
' otherwise keep checking
Return False
End If
Next
' All dependency objects are valid
Return True
End Function
End Class
End Namespace
Este cdigo enumera todos los objetos de dependencia de una ventana y, si hay alguno que no es vlido (si
devuelve GetHasError, el control no vlido obtiene el foco, el mtodo IsValid devuelve false y la ventana se
considera no vlida.
Cuando un cuadro de dilogo es vlido, se puede cerrar y devolver sin ningn riesgo. Como parte del proceso
de retorno, debe devolver un resultado a la funcin que realiza la llamada.
Establecer el resultado del dilogo modal
Abrir un cuadro de dilogo mediante ShowDialog es fundamentalmente como llamar a un mtodo: el cdigo
que abri el cuadro de dilogo mediante ShowDialog espera hasta que vuelva ShowDialog. Cuando vuelve
Pag 90 de 445
Pag 91 de 445
Sin embargo, su comportamiento es ligeramente diferente, como se describe en las secciones siguientes.
Abrir un cuadro de dilogo no modal
Un cuadro de dilogo no modal se abre llamando al mtodo Show.
<!--Main Window-->
Imports System ' EventArgs
Imports System.ComponentModel ' CancelEventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextChangedEventArgs
Imports Microsoft.Win32 ' OpenFileDialog
Namespace SDKSample
Public Class MainWindow
Inherits Window
Private Sub editFindMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim dlg As New FindDialogBox(Me.documentTextBox)
dlg.Owner = Me
AddHandler dlg.TextFound, New TextFoundEventHandler(AddressOf Me.dlg_TextFound)
dlg.Show()
End Sub
A diferencia de ShowDialog, Show vuelve inmediatamente. Por consiguiente, la ventana que realiza la llamada
no puede distinguir cundo se cierra el cuadro de dilogo no modal y, en consecuencia, no sabe cundo
comprobar los resultados del cuadro de dilogo o recibir los datos del cuadro de dilogo para continuar el
procesamiento. En su lugar, el cuadro de dilogo debe crear una manera alternativa de devolver datos a la
ventana que realiza la llamada para el procesamiento.
Procesar datos devueltos desde un cuadro de dilogo no modal
En este ejemplo, FindDialogBox puede devolver uno o ms resultados de bsqueda a la ventana principal, segn
el texto que se est buscando, sin ninguna frecuencia concreta. Como con un cuadro de dilogo modal, un
cuadro de dilogo no modal puede devolver resultados mediante propiedades. Sin embargo, la ventana que
posee el cuadro de dilogo necesita saber cundo debe comprobar esas propiedades. Una manera de habilitar
esto es que el cuadro de dilogo implemente un evento que se produzca siempre que se encuentre el texto.
FindDialogBox implementa TextFoundEvent para este propsito, que requiere primero un delegado.
Namespace SDKSample
Public Delegate Sub TextFoundEventHandler(ByVal sender As Object, ByVal e As EventArgs)
End Namespace
Con el delegado TextFoundEventHandler, FindDialogBox implementa TextFoundEvent.
Imports System ' EventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextBox, TextChangedEventArgs
Imports System.Text.RegularExpressions ' Regex
Namespace SDKSample
Public Class FindDialogBox
Inherits Window
Public Event TextFound As TextFoundEventHandler
Protected Overridable Sub OnTextFound()
RaiseEvent TextFound(Me, EventArgs.Empty)
End Sub
End Class
End Namespace
Por consiguiente, Find puede provocar el evento cuando se encuentra un resultado de bsqueda.
Imports System ' EventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextBox, TextChangedEventArgs
Imports System.Text.RegularExpressions ' Regex
Namespace SDKSample
Public Class FindDialogBox
Inherits Window
Private Sub findNextButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Me.Index = match.Index
Me.Length = match.Length
RaiseEvent TextFound(Me, EventArgs.Empty)
Pag 92 de 445
Como alternativa, el cdigo puede llamar a Close cuando se haga clic en el botn Cerrar.
Imports System ' EventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextBox, TextChangedEventArgs
Imports System.Text.RegularExpressions ' Regex
Namespace SDKSample
Public Class FindDialogBox
Inherits Window
Private Sub closeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
MyBase.Close()
End Sub
End Class
End Namespace
Pag 93 de 445
Pag 94 de 445
Pag 95 de 445
Pag 96 de 445
En el marcado, el elemento Page debe incluir el atributo x:Class. Al generar la aplicacin, la existencia
de x:Class en el archivo de marcado permite que Microsoft build engine (MSBuild) cree una clase
partial que se derive de Pagey tenga el nombre especificado por el atributo x:Class. Para ello, es
necesario
agregar
una
declaracin
de
espacio
de
(xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml").
nombres
La
clase
XML
para
partial
el
esquema
generada
XAML
implementa
InitializeComponent, al que se llama para registrar los eventos y establecer las propiedades que se
implementan en el marcado.
En el archivo de cdigo subyacente, la clase debe ser una clase partial con el mismo nombre que el
que especific el atributo x:Class en el marcado, y debe derivarse de Page. Esto permite que el archivo
de cdigo subyacente se asocie a la clase partial que se genera para el archivo de marcado cuando se
crea la aplicacin.
En el archivo de cdigo subyacente, la clase Page debe implementar un constructor que llame al
mtodo InitializeComponent. InitializeComponent se implementa mediante la clase partial generada
del archivo de marcado para registrar eventos y establecer las propiedades que se definen en el
marcado.
Nota:
Al agregar un nuevo objeto Page a su proyecto con Microsoft Visual Studio, se implementa Page utilizando
el marcado y el cdigo subyacente; este control incluye la configuracin necesaria para crear la asociacin
entre los archivos de cdigo subyacente y de marcado tal como aqu se describe.
Cuando ya tenga un objeto Page, podr navegar a l. Para especificar el primer objeto Page al que navega una
aplicacin, necesita configurar el objeto Page de inicio.
Configurar una pgina de inicio
Las XBAPs exigen que una determinada cantidad de infraestructura de la aplicacin est hospedada en un
explorador. En WPF, la clase Application forma parte de una definicin de aplicacin que establece la
infraestructura de aplicacin necesaria.
Una definicin de aplicacin se suele implementar mediante marcado y cdigo subyacente, con el archivo de
marcado configurado como un elemento ApplicationDefinition de MSBuild. A continuacin, se incluye una
definicin de aplicacin para XBAP.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App" />
using System.Windows; // Application
namespace SDKSample
{
public partial class App : Application { }
}
XBAP puede utilizar su definicin de aplicacin para especificar un objeto Page de inicio, que es el objeto
Page que se carga automticamente cuando se inicia XBAP. Para ello, se establece la propiedad StartupUri con
el identificador de recursos uniforme (URI) del objeto Page deseado.
Nota:
Normalmente, el objeto Page se compila o se implementa con una aplicacin. En tales casos, el URI que
identifica un objeto Page es un pack URI, que es un URI compatible con el esquema pack. Tambin puede
navegar al contenido mediante el esquema http, que se describe a continuacin.
Puede establecer StartupUri mediante declaracin en el marcado, como se muestra en el ejemplo siguiente.
Pag 97 de 445
El pack URI del objeto Page al que se va navegar, especificado por el atributo NavigateUri.
Pag 98 de 445
El contenido en el que un usuario puede hacer clic para iniciar la navegacin, como texto e imgenes
(para saber qu contenido se puede incluir en el elemento Hyperlink).
En la ilustracin siguiente se muestra una XBAP con Page que tiene un objeto Hyperlink.
Como era de prever, al hacer clic en Hyperlink XBAP se desplaza al control Page, identificado por el atributo
NavigateUri. Adems, la XBAP agrega una entrada para el objeto Page anterior a la lista Pginas recientes de
Internet Explorer 7. Esto se muestra en la ilustracin siguiente.
Adems de permitir la navegacin de un objeto Page a otro, Hyperlink admite la navegacin por fragmentos.
Navegacin por fragmentos
La navegacin por fragmentos es la navegacin a un fragmento de contenido en el objeto Page u otro objeto
Page. En WPF, un fragmento de contenido es el contenido incluido en un elemento con nombre. Un elemento
con nombre es un elemento que tiene establecido su atributo Name. En el marcado siguiente se muestra un
elemento TextBlock con nombre que contiene un fragmento de contenido.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page With Fragments" >
...
<!-- Content Fragment called "Fragment1" -->
<TextBlock Name="Fragment1">
Ea vel dignissim te aliquam facilisis ...
</TextBlock>
...
</Page>
Para que un objeto Hyperlink navegue a un fragmento de contenido, el atributo NavigateUri debe incluir lo
siguiente:
Pag 99 de 445
En esta seccin se describe la implementacin de navegacin por fragmentos predeterminada en WPF. WPF
permite tambin implementar un esquema de navegacin por fragmentos propio, que requiere
parcialmente que se controle el evento NavigationService.FragmentNavigation.
Nota importante:
Slo puede navegar a fragmentos en pginas XAML independientes (archivos de XAML de slo marcado con
Page como elemento raz) si las pginas se pueden examinar mediante HTTP.
Sin embargo, una pgina XAML independiente puede navegar a sus propios fragmentos.
Servicio de navegacin
Aunque Hyperlink permite que un usuario inicie la navegacin en un objeto Page determinado, la clase
NavigationService es la encargada de buscar y descargar la pgina. Bsicamente, NavigationService
proporciona la capacidad de procesar una solicitud de navegacin en nombre de cdigo cliente, como Hyperlink.
Adems, NavigationService implementa la compatibilidad de nivel superior para realizar el seguimiento y dirigir
las solicitudes de navegacin.
Al hacer clic en Hyperlink, WPF llama a NavigationService.Navigate para buscar y descargar el objeto Page en el
pack URI especificado. El objeto Page descargado se convierte en un rbol de objetos cuyo objeto raz es una
instancia del objeto Page descargado. En la propiedad NavigationService.Content se almacena una referencia al
objeto
Page raz.
El
pack
URI
del
contenido
al
que
se
naveg
se
almacena
en
la
propiedad
Cuando tenga que crear una instancia de Page utilizando un constructor no predeterminado.
Cuando tenga que establecer propiedades en el objeto Page antes de navegar a l.
Cuando el objeto Page al que hay que navegar slo pueda determinarse en tiempo de ejecucin.
En estas situaciones, deber escribir cdigo para iniciar la navegacin mediante programacin llamando al
mtodo Navigate del objeto NavigationService. Para ello, es necesario obtener una referencia a un objeto
NavigationService.
Obtener una referencia a NavigationService
Por los motivos explicados en la seccin Hosts de navegacin, una aplicacin de WPF puede tener ms de un
objeto
NavigationService.
Esto
implica
que
el
cdigo
necesita
un
modo
de
encontrar
un
objeto
obtener
una
referencia
un
objeto
NavigationService
llamando
al
mtodo
static
GetNavigationService. Para obtener el objeto NavigationService que naveg a un objeto Page determinado,
tendr que pasar una referencia al objeto Page como argumento del mtodo GetNavigationService. En el
ejemplo de cdigo siguiente se muestra cmo obtener el NavigationService para el objeto Page actual.
using System.Windows.Navigation; // NavigationServce
...
// Get a reference to the NavigationService that navigated to this Page
NavigationService ns = NavigationService.GetNavigationService(this);
Para simplificar la bsqueda de un NavigationService para un objeto Page, Page implementa la propiedad
NavigationService. Esto se muestra en el ejemplo siguiente.
Navigating. Se produce cuando se solicita una nueva navegacin. Se puede utilizar para cancelar la
navegacin.
En general, los objetos Page no tienen que ocuparse de estos eventos. Es ms probable que una aplicacin
tenga que ocuparse de ellos, razn por la cual la clase Application provoca tambin estos eventos:
Application.Navigating
Application.NavigationProgress
Application.Navigated
Application.NavigationFailed
Application.NavigationStopped
Application.LoadCompleted
Application.FragmentNavigation
Cada vez que NavigationService provoca un evento, la clase Application provoca el evento correspondiente.
Frame y NavigationWindow ofrecen los mismos eventos para detectar la navegacin dentro de sus mbitos
respectivos.
En algunos casos, un objeto Page podra tener que ocuparse de estos eventos. Por ejemplo, un objeto Page
podra controlar el evento Navigating para determinar si debe cancelar o no la navegacin fuera del propio
objeto. Esto se muestra en el ejemplo siguiente.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.CancelNavigationPage">
<Button Click="button_Click">Navigate to Another Page</Button>
</Page>
using System; // Uri, UriKind
using System.Windows; // RoutedEventArgs, MessageBox, MessageBoxResult
using System.Windows.Controls; // Page
using System.Windows.Navigation; // NavigationService, NavigatingCancelEventArgs
namespace SDKSample
{
public partial class CancelNavigationPage : Page
{
public CancelNavigationPage()
{
InitializeComponent();
// Can only access the NavigationService when the page has been loaded
this.Loaded += new RoutedEventHandler(CancelNavigationPage_Loaded);
this.Unloaded += new RoutedEventHandler(CancelNavigationPage_Unloaded);
}
void button_Click(object sender, RoutedEventArgs e)
{
// Force WPF to download this page again
this.NavigationService.Navigate(new Uri("AnotherPage.xaml",
UriKind.Relative));
}
void CancelNavigationPage_Loaded(object sender, RoutedEventArgs e)
{
this.NavigationService.Navigating += new
NavigatingCancelEventHandler(NavigationService_Navigating);
}
void CancelNavigationPage_Unloaded(object sender, RoutedEventArgs e)
{
this.NavigationService.Navigating -= new
NavigatingCancelEventHandler(NavigationService_Navigating);
}
void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
{
// Does the user really want to navigate to another page?
MessageBoxResult result;
result = MessageBox.Show("Do you want to leave this page?", "Navigation
Request", MessageBoxButton.YesNo);
// If the user doesn't want to navigate away, cancel the navigation
if (result == MessageBoxResult.No) e.Cancel = true;
}
}
Si registra un controlador con un evento de navegacin desde un objeto Page, como en el ejemplo anterior,
tambin debe cancelar el registro del controlador de eventos. Si no lo hace, se podran producir efectos
secundarios relacionados con el modo en que la navegacin de WPF recuerda la navegacin de Page a travs
del diario.
Recordar la navegacin con el diario
WPF utiliza dos pilas para recordar las pginas desde las que se ha navegado: una pila de retroceso y una pila
de avance. Al navegar desde el objeto Page actual a un nuevo objeto Page o avanzar a un objeto Page
existente, el objeto Page actual se agrega a la pila de retroceso. Al retroceder desde el objeto Page al
objeto Page anterior, el objeto Page se agrega a la pila de avance. La pila de retroceso, la pila de avance y las
funciones para administrar estas pilas reciben en conjunto el nombre de diario. Cada elemento de la pila de
retroceso y de la pila de avance es una instancia de la clase JournalEntry y se hace referencia a l como una
entrada del diario.
Navegar por el diario desde Internet Explorer 7
Conceptualmente, el diario funciona de la misma manera que los botones Atrs y Adelante de Internet Explorer
7. Este comportamiento se muestra en la siguiente ilustracin.
Para las XBAPs hospedadas por Internet Explorer 7, WPF integra el diario en la interfaz de usuario de
navegacin de Internet Explorer 7. Esto permite que los usuarios naveguen a pginas de una aplicacin XBAP
mediante los botones Atrs, Adelante y Pginas recientes de Internet Explorer 7. El diario no se integra en
Microsoft Internet Explorer 6 del mismo modo que en Internet Explorer 7. En lugar de ello, WPF representa una
interfaz de usuario de navegacin alternativa.
Nota importante:
En Internet Explorer 7, cuando un usuario sale y vuelve a una XBAP, slo se conservan en el diario las
entradas de las pginas que no se mantuvieron activas.
De forma predeterminada, el texto de cada Page que aparece en la lista Pginas recientes de Internet Explorer
7 es el URI de Page. En muchos casos, esto no le resulta particularmente significativo al usuario.
Afortunadamente, puede cambiar el texto mediante una las opciones siguientes:
1.
2.
3.
4.
El orden en que se indican las opciones es el mismo que el orden de prioridad de la bsqueda de texto. Por
ejemplo, si se establece JournalEntry.Name, se omiten los dems valores.
En el ejemplo siguiente se utiliza el atributo Page.Title para cambiar el texto que aparece para una entrada del
diario.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
GoBack
GoForward
CanGoBack
CanGoForward
Aunque el uso del comportamiento del diario predeterminado puede ahorrar memoria, podra dar lugar a una
reduccin del rendimiento de la representacin de cada pgina, ya que crear una nueva instancia de un objeto
Page puede ser laborioso, especialmente si tiene mucho contenido. Si necesita conservar una instancia de Page
Cuando un objeto Page no se mantiene activo, no debe realizar ninguna de las operaciones siguientes:
Si realiza alguna de estas operaciones, crear referencias que obliguen al objeto Page a conservarse en
memoria, incluso despus de que se quite del diario.
En general, debera optar por el comportamiento Page predeterminado, que no mantiene el objeto Page activo.
Sin embargo, este comportamiento tiene implicaciones que afectan al estado, descritas en la siguiente seccin.
Conservar el estado del contenido con el historial de navegacin
Si un objeto Page no se mantiene activo y tiene controles que recopilan datos del usuario, qu ocurre con los
datos si un usuario avanza y retrocede al objeto Page? Desde la perspectiva de la experiencia del usuario, el
usuario debe esperar ver los datos que especific previamente. Desgraciadamente, como se crea una nueva
instancia de Page con cada navegacin, se crean nuevas instancias de los controles que recopilaron los datos y
los datos se pierden.
Por fortuna, el diario proporciona compatibilidad para recordar los datos durante la navegacin por Page,
incluidos los datos de los controles. En concreto, la entrada del diario de cada Page acta como un contenedor
temporal para el estado de Page asociado. En los pasos siguientes se explica brevemente cmo funciona esta
compatibilidad cuando se navega desde un objeto Page:
1.
2.
3.
Cuando se retrocede al objeto Page, gracias al diario, se producen las siguientes operaciones:
1.
Se crea una instancia de Page (la entrada superior del diario en la pila de retroceso).
El objeto Page se actualiza con el estado que se almacen con la entrada del diario para el objeto
Page.
3.
WPF utiliza automticamente esta compatibilidad cuando se utilizan los controles siguientes en un objeto Page:
CheckBox
ComboBox
Expander
Frame
ListBox
ListBoxItem
MenuItem
ProgressBar
RadioButton
Slider
TabControl
TabItem
TextBox
Si un objeto Page utiliza estos controles, los datos registrados en ellos se recuerdan durante la navegacin por
Page, como se muestra en Favorite colorListBox en la ilustracin siguiente.
Cuando un objeto Page tiene controles distintos de los de la lista anterior, o cuando el estado se almacena en
objetos personalizados, debe escribir cdigo que permita al diario recordar el estado durante la navegacin por
Page.
Si necesita recordar peque;os segmentos de estado durante la navegacin por Page, puede utilizar
propiedades
de
dependencia
que
se
configuran
con
el
marcador
de
metadatos
de
FrameworkPropertyMetadata.Journal.
Si el estado que el objeto Page necesita recordar durante la navegacin consta de varios segmentos de datos,
puede resultarle ms sencillo encapsular el estado en una clase nica e implementar la interfaz
IProvideCustomContentState.
Si necesita desplazarse por varios estados de un mismo objeto Page, sin navegar desde el propio objeto Page,
puede utilizar IProvideCustomContentState y NavigationService.AddBackEntry.
Cookies
Las aplicaciones de WPF independientes y las XBAPs pueden crear y administrar cookies.
Se puede tener acceso a las cookies creadas por una XBAP desde el explorador.
Las XBAPs del mismo dominio pueden crear y compartir cookies.
Las XBAPs y las pginas HTML del mismo dominio pueden crear y compartir cookies.
Las cookies se envan cuando las XBAPs y las pginas XAML independientes crean solicitudes web.
Las XBAPs de alto nivel y las XBAPs hospedadas en IFRAMES pueden tener acceso a las cookies.
La compatibilidad de las cookies en WPF es la misma para todos los exploradores compatibles
(Internet Explorer 7, Microsoft Internet Explorer 6 y Firefox 2.0+).
En Microsoft Internet Explorer 6 e Internet Explorer 7, WPF aplica la directiva P3P relacionada con las
cookies, especialmente en relacin con las XBAPs propias y de otros fabricantes.
Navegacin estructurada
Si necesita pasar datos de un objeto Page a otro, puede pasarlos como argumentos a un constructor no
predeterminado de Page. Tenga en cuenta que si utiliza esta tcnica, debe mantener el objeto Page activo ya
que, de lo contrario, la prxima vez que navegue al objeto Page, WPF crear una nueva instancia del objeto
Page mediante el constructor predeterminado.
Page puede implementar tambin propiedades que se establezcan con los datos que debe pasar. Sin embargo,
las cosas se complican cuando un objeto Page tiene que volver a pasar datos al objeto Page que naveg a l. El
problema reside en que la navegacin no permite de forma nativa mecanismos que garanticen que se vuelva a
un
objeto
Page
una
vez
abandonado.
Esencialmente,
la
navegacin
no
admite
la
semntica
de
llamada/devolucin. Para resolver este problema, WPF proporciona la clase PageFunction<(Of <(T>)>), que se
puede utilizar para garantizar que se vuelva a un objeto Page de un modo previsible y estructurado.
La clase NavigationWindow
Llegados a este punto, ya se han abordado los servicios de navegacin que probablemente utilizar con ms
frecuencia para crear aplicaciones con contenido navegable. Estos servicios se describen en el contexto de
XBAPs, pero no se limitan a XBAPs. Los sistemas operativos modernos y las aplicaciones de Windows
Para incorporar una navegacin similar a la de los exploradores en sus aplicaciones independientes, puede usar
la clase NavigationWindow. NavigationWindow se deriva de Window y se extiende con la misma compatibilidad
de navegacin proporcionada por las XBAPs. Puede utilizar NavigationWindow como la ventana principal de su
aplicacin independiente o como una ventana secundaria (por ejemplo, un cuadro de dilogo).
Para implementar NavigationWindow, al igual que con la mayora de las clases de nivel superior de WPF
(Window, Page, etc.), se utiliza una combinacin de marcado y cdigo subyacente. Esta implementacin se
muestra en el ejemplo siguiente.
<NavigationWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MainWindow"
Source="HomePage.xaml"/>
using System.Windows.Navigation; // NavigationWindow
namespace SDKSample
{
public partial class MainWindow : NavigationWindow
{
public MainWindow()
{
InitializeComponent();
}
}
}
Este cdigo crea un objeto NavigationWindow que navega automticamente a un objeto Page (HomePage.xaml)
cuando se abre NavigationWindow. Si NavigationWindow es la ventana principal de la aplicacin, puede utilizar
el atributo StartupUri para iniciarla. Esto queda reflejado en el marcado siguiente.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />
En la ilustracin siguiente se muestra el objeto NavigationWindow como la ventana principal de una aplicacin
independiente.
En la ilustracin, puede ver que NavigationWindow tiene un ttulo, aunque no se estableci en el cdigo de
implementacin de NavigationWindow del ejemplo anterior. El ttulo se establece mediante la propiedad
WindowTitle, que se muestra en el cdigo siguiente.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Home Page"
WindowTitle="NavigationWindow">
...
</Page>
El establecimiento de propiedades WindowWidth y WindowHeight afecta tambin al objeto NavigationWindos.
Normalmente, implementar su propio NavigationWindow cuando necesite personalizar su comportamiento o su
apariencia. Si no es el caso, hay una alternativa ms simple. Si especifica el pack URI de un objeto Page como
StartupUri en una aplicacin independiente, Application crea automticamente un objeto NavigationWindow
para hospedar el objeto Page. Esta operacin se muestra en el marcado siguiente.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Como puede ver, NavigationWindow muestra los botones Atrs y Adelante con el formato de Internet Explorer
7, que permiten a los usuarios navegar por el diario. Estos botones proporcionan la misma experiencia del
usuario, como se muestra en la ilustracin siguiente.
Si sus pginas proporcionan su propia compatibilidad e interfaz de usuario de navegacin por el diario, puede
ocultar los botones Atrs y Adelante mostrados por NavigationWindow estableciendo el valor de la propiedad
ShowsNavigationUI en false. Tambin puede utilizar la compatibilidad de personalizacin de WPF para
reemplazar la interfaz de usuario del propio NavigationWindow.
La clase Frame
Tanto el explorador como NavigationWindow son ventanas que hospedan contenido navegable. En algunos
casos, las aplicaciones tienen contenido que no necesita hospedarse en una ventana completa. Este contenido
se puede hospedar dentro de otro contenido. Puede insertar contenido navegable en otro contenido utilizando la
clase Frame. Frame proporciona la misma compatibilidad que NavigationWindow y XBAPs.
En el ejemplo siguiente se muestra cmo agregar mediante declaracin un objeto Frame a Page con el
elemento Frame.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page that Hosts a Frame"
WindowWidth="250"
WindowHeight="250">
...
<Frame Source="FramePage1.xaml" />
...
</Page>
Este marcado establece el atributo Source del elemento Frame con un pack URI para el Page al que Frame debe
navegar inicialmente. En la ilustracin siguiente se muestra una XBAP con un objeto Page que tiene un Frame
que ha navegado por varias pginas.
No slo tiene que utilizar Frame dentro del contenido de un objeto Page. Tambin es habitual hospedar un
Frame dentro del contenido de un objeto Window.
De forma predeterminada, Frame slo utiliza su propio diario si no existe ningn otro. Si un Frame forma parte
del contenido que se hospeda dentro de un objeto NavigationWindow o de una XBAP, Frame utiliza el diario que
pertenece a NavigationWindow o XBAP. Sin embargo, en algunas ocasiones, es posible que un objeto Frame
tenga que ocuparse de su propio diario. Esto se muestra en la ilustracin siguiente.
En este caso, puede configurar el objeto Frame para que utilice su propio diario estableciendo la propiedad
JournalOwnership de Frame en OwnsJournal. Esto queda reflejado en el marcado siguiente.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page that Hosts a Frame"
WindowWidth="250"
WindowHeight="250">
...
<Frame Source="FramePage1.xaml" JournalOwnership="OwnsJournal" />
...
</Page>
En la ilustracin siguiente se muestra el efecto de navegar dentro de un objeto Frame que utiliza su propio
diario.
Observe que es la interfaz de usuario de navegacin de Frame y no Internet Explorer 7 la que muestra las
entradas del diario.
Nota:
Si un objeto Frame forma parte del contenido hospedado en Window, Frame utiliza su propio diario y, por
tanto, presenta su propia interfaz de usuario de navegacin.
Si la experiencia de usuario requiere que un objeto Frame proporcione su propio diario sin mostrar la interfaz
de
usuario
de
navegacin,
puede
ocultar
la
interfaz
de
usuario
de
navegacin
estableciendo
Bsicamente, este host permite que NavigationWindow y Frame proporcionen la misma compatibilidad de
navegacin que la que proporciona una XBAP cuando se hospeda en el explorador.
Adems de utilizar NavigationService y un diario, los hosts de navegacin implementan los mismos miembros
que implementa NavigationService. Esto se muestra en la ilustracin siguiente.
Esto permite programar directamente en ellos la compatibilidad de navegacin. Puede considerar esta opcin si
necesita proporcionar una interfaz de usuario de navegacin personalizada para un objeto Frame hospedado en
Window. Adems, ambos tipos implementan miembros adicionales relacionados con la navegacin, entre los
que
se
incluyen
BackStack
(NavigationWindow.BackStack,
Frame.BackStack)
ForwardStack
Considere, por ejemplo, el contenido siguiente que est almacenado como un archivo XAML independiente,
Person.xaml.
<!-- Person.xaml -->
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<TextBlock FontWeight="Bold">Name:</TextBlock>
<TextBlock>Nancy Davolio</TextBlock>
<LineBreak />
<TextBlock FontWeight="Bold">Favorite Color:</TextBlock>
<TextBlock>Yellow</TextBlock>
</TextBlock>
Al hacer doble clic en el archivo, el explorador se abre, se desplaza al contenido y lo muestra. Este
comportamiento se muestra en la ilustracin siguiente.
Un archivo XAML independiente se puede agregar a los favoritos del explorador o convertirse en la pgina
principal del explorador.
Una limitacin de los archivos XAML independientes es que slo permiten hospedar contenido que se pueda
ejecutar de forma segura en una relacin de confianza parcial. Por ejemplo, Window no puede ser el elemento
raz de un archivo XAML independiente.
Navegar a archivos HTML
Como cabe esperar, tambin es posible navegar a HTML. Slo tiene que proporcionar un URI que utilice el
esquema http. Por ejemplo, el XAML siguiente muestra un objeto Frame que navega a una pgina HTML.
<Frame Source="http://www.microsoft.com/default.aspx" />
Para navegar a HTML se requieren permisos especiales. Por ejemplo, no puede navegar desde una XBAP que se
ejecute en el recinto de seguridad de confianza parcial de la zona de Internet.
Navegar a objetos personalizados
Si tiene datos que estn almacenados como objetos personalizados, una manera de mostrar esos datos es
crear un objeto Page con contenido enlazado a esos objetos. Si puede prescindir del trabajo adicional que
supone crear una pgina completa para mostrar simplemente los objetos, puede navegar directamente a ellos.
Considere la clase Person que se implementa en el cdigo siguiente.
using System.Windows.Media; // Color
namespace SDKSample
{
public class Person
{
string name;
Color favoriteColor;
En esta ilustracin, puede ver que no se muestra ninguna informacin til. De hecho, el valor que se muestra
es el valor devuelto por el mtodo ToString para el objeto Person; de forma predeterminada, ste es el nico
valor que WPF puede utilizar para representar el objeto. Podra invalidar el mtodo ToString para devolver
informacin ms til, pero seguira siendo simplemente un valor de cadena. Una tcnica posible que aprovecha
las funciones de presentacin WPF es usar una plantilla de datos. Puede implementar una plantilla de datos que
WPF pueda asociar a un objeto de un tipo determinado. En el cdigo siguiente se muestra una plantilla de datos
para el objeto Person.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample"
x:Class="SDKSample.App"
StartupUri="HomePage.xaml">
<Application.Resources>
<!-- Data Template for the Person Class -->
<DataTemplate DataType="{x:Type local:Person}">
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<TextBlock FontWeight="Bold">Name:</TextBlock>
<TextBlock Text="{Binding Path=Name}" />
Una ventaja de esta tcnica es la coherencia conseguida al ser capaz de reutilizar la plantilla de datos para
mostrar los objetos con un aspecto similar en cualquier lugar de la aplicacin.
Seguridad
La compatibilidad de navegacin de WPF permite utilizar las XBAPs para toda la navegacin por Internet, y
permite que las aplicaciones hospeden contenido de otros fabricantes. Para proteger las aplicaciones y a los
usuarios de un comportamiento malintencionado, WPF proporciona un conjunto de caractersticas de seguridad
La pgina que llama navega a la pgina llamada, con la opcin de pasar parmetros requeridos por la
pgina llamada.
La pgina llamada, cuando un usuario ha terminado de usar la pgina que llama, puede devolver
especficamente a la pgina de llamada lo siguiente:
Devolucin de informacin de estado, que describe cmo se complet la pgina que llama
(por ejemplo, si un usuario presion un botn Aceptar o un botn Cancelar).
Devolucin de los datos recopilados del usuario (por ejemplo, los detalles del nuevo
empleado).
Cuando la pgina que llama vuelve a la pgina llamada, la pgina llamada se quita del historial de
navegacin, para aislar cada instancia de la pgina llamada.
Puede implementar estos comportamientos utilizando un objeto PageFunction<(Of <(T>)>) como pgina
llamada.
Navegacin estructurada con PageFunction
En este tema se muestra cmo implementar los mecanismos bsicos de navegacin estructurada que implica
un
objeto
PageFunction<(Of
<(T>)>)nico.
En
este
ejemplo,
un
objeto
Page
llama
un
objeto
2.
3.
Sin embargo, como ver pronto, todava necesitar utilizar cdigo para crear instancias y navegar a la pgina
llamada para recopilar los datos devueltos por la pgina llamada. Por esta razn, PageFunction<(Of <(T>)>)
necesita mantenerse vivo; de lo contrario, la prxima vez que navegue al objeto PageFunction<(Of <(T>)>),
WPF crear una instancia de PageFunction<(Of <(T>)>) utilizando el constructor predeterminado.
Para que la pgina llamada puede volver, sin embargo, necesita devolver datos que puedan ser recuperados
por la pgina que llama.
Devolver el resultado y los datos de una tarea a una pgina que llama
Cuando el usuario ha terminado de utilizar la pgina llamada, lo que sucede en este ejemplo al presionar los
botones Aceptar o Cancelar, la pgina llamada debe volver. Puesto que la pgina que llama utiliz la pgina
llamada para recopilar los datos del usuario, la pgina que llama requiere dos tipos de informacin:
1.
Si el usuario cancel la pgina llamada (presionando el botn Aceptar o el botn Cancelar en este
ejemplo). Esto permite decidir a la pgina que llama si debe procesar los datos que la pgina de llamada
recopil del usuario.
2.
Para devolver informacin, PageFunction<(Of <(T>)>) implementa el mtodo OnReturn. En el cdigo siguiente
se muestra cmo llamarlo.
Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
...
Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Accept when Ok button is clicked
Me.OnReturn(New ReturnEventArgs(Of String)(Me.dataItem1TextBox.Text))
End Sub
Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Cancel
Me.OnReturn(Nothing)
End Sub
End Class
End Namespace
Topologa fija: se define en tiempo de compilacin y no cambia en tiempo de ejecucin. Las topologas
fijas son tiles para la navegacin a travs de una secuencia fija de pginas en orden lineal o
jerrquico.
Topologa dinmica: se define en tiempo de ejecucin basndose en los datos proporcionados por el
usuario, la aplicacin o el sistema. Las topologas dinmicas son tiles cuando se puede navegar por
las pginas en secuencias diferentes.
Aunque es posible crear topologas de navegacin mediante pginas, en los ejemplos se utilizan funciones de
pgina, porque proporcionan compatibilidad adicional que simplifica la compatibilidad con el paso y la
devolucin de datos a travs de las pginas de una topologa.
Navegacin por una topologa fija lineal
Los comportamientos tpicos para navegar por una topologa fija lineal son:
Navegar desde la pgina de llamada a una pgina de inicio que inicializa el asistente y navega a la
primera pgina de este ltimo. No se requiere una pgina de inicio (PageFunction<(Of <(T>)>) sin
interfaz de usuario), ya que una pgina de llamada puede llamar directamente a la primera pgina del
asistente. Sin embargo, el uso de una pgina de inicio puede simplificar la inicializacin del asistente,
especialmente si es compleja.
El usuario puede navegar de una pgina a otra mediante los botones (o hipervnculos) de retroceso y
avance (Atrs y Siguiente).
El usuario puede aceptar el asistente en la ltima pgina del mismo presionando un botn de
finalizacin (Finalizar).
Cuando se completa el asistente (se acepta o se cancela), las pginas que componen el asistente se
quitan del diario. De este modo, cada instancia del asistente se mantiene aislada, lo que evita posibles
anomalas en los datos o en el estado.
Esta estructura se denomina topologa fija jerrquica y la aplicacin o el usuario suelen determinar en tiempo
de ejecucin la secuencia en la que se recorre la jerarqua. En tiempo de ejecucin, cada pgina de la jerarqua
que permite la navegacin a dos o ms otras pginas recolecta los datos necesarios para determinar a qu
pgina se va a navegar. En la ilustracin siguiente se muestra una de las distintas secuencias de navegacin
posibles basndose en la ilustracin anterior.
Aunque la secuencia en la que se navega por las pginas en una estructura fija jerrquica se determina en
tiempo de ejecucin, la experiencia del usuario es igual que en una topologa fija lineal:
Navegar desde la pgina de llamada a una pgina de inicio que inicializa el asistente y navega a la
primera pgina de este ltimo. No se requiere una pgina de inicio (PageFunction<(Of <(T>)>) sin
interfaz de usuario), ya que una pgina de llamada puede llamar directamente a la primera pgina del
asistente. Sin embargo, el uso de una pgina de inicio puede simplificar la inicializacin del asistente,
especialmente si es compleja.
El usuario puede navegar de una pgina a otra mediante los botones (o hipervnculos) de retroceso y
avance (Atrs y Siguiente).
El usuario puede aceptar el asistente en la ltima pgina del mismo presionando un botn de
finalizacin (Finalizar).
Cuando se completa el asistente (se acepta o se cancela), las pginas que componen el asistente se
quitan del diario. De este modo, cada instancia del asistente se mantiene aislada, lo que evita posibles
anomalas en los datos o en el estado.
En la figura siguiente se muestra una secuencia de navegacin elegida por el usuario en tiempo de ejecucin.
La secuencia de navegacin se denomina topologa generada dinmicamente. Para el usuario, al igual que en
las otras topologas de navegacin, la experiencia es igual que en las topologas anteriores:
Navegar desde la pgina de llamada a una pgina de inicio que inicializa el asistente y navega a la
primera pgina de este ltimo. No se requiere una pgina de inicio (PageFunction<(Of <(T>)>) sin
interfaz de usuario), ya que una pgina de llamada puede llamar directamente a la primera pgina del
asistente. Sin embargo, el uso de una pgina de inicio puede simplificar la inicializacin del asistente,
especialmente si es compleja.
El usuario puede navegar de una pgina a otra mediante los botones (o hipervnculos) de retroceso y
avance (Atrs y Siguiente).
El usuario puede aceptar el asistente en la ltima pgina del mismo presionando un botn de
finalizacin (Finalizar).
Cuando se completa el asistente (se acepta o se cancela), las pginas que componen el asistente se
quitan del diario. De este modo, cada instancia del asistente se mantiene aislada, lo que evita posibles
anomalas en los datos o en el estado.
La propiedad Source
El mtodo Navigate.
// Navigate to URI using the Source property
this.Source = new Uri("HomePage.xaml", UriKind.Relative);
// Navigate to URI using the Navigate method
this.Navigate(new Uri("HomePage.xaml", UriKind.Relative));
// Navigate to object using the Navigate method
2.4.4.13. Cmo: Usar Mailto: para Enviar Correo desde una Pgina
En este ejemplo se muestra cmo utilizar Hyperlink junto con un identificador de recursos uniforme (URI) de
mailto:.
Ejemplo
En el cdigo siguiente se muestra cmo utilizar un identificador de recursos uniforme (URI) de mailto: para
abrir una nueva ventana de correo que contiene una direccin de correo electrnico, una direccin de correo
electrnico y un asunto, y una direccin de correo electrnico, un asunto y un cuerpo de mensaje.
Por ejemplo, el modelo de complementos del Reproductor de Windows Media permite a los desarrolladores de
otros fabricantes implementar complementos que extienden el Reproductor de Windows Media de diversas
maneras, entre las que estn la creacin de descodificadores y codificadores para los formatos multimedia que
el Reproductor de Windows Media no admite de forma nativa (por ejemplo, DVD y MP3), efectos de audio y
mscaras. Cada modelo de complementos se ha generado de modo que exponga la funcionalidad que es nica
de una aplicacin, aunque hay varias entidades y comportamientos que son comunes a todos los modelos de
complementos.
Las tres entidades principales de las tpicas soluciones de extensibilidad mediante complementos son los
contratos, los complementos y las aplicaciones host. Los contratos definen cmo se integran los complementos
con las aplicaciones host de dos maneras:
Los complementos se integran con la funcionalidad que implementan las aplicaciones host.
Las aplicaciones host exponen la funcionalidad para los complementos con los que se integran.
Para poder utilizar complementos, las aplicaciones host deben encontrarlos y cargarlos en tiempo de ejecucin.
Por consiguiente, las aplicaciones que admiten complementos tienen las siguientes responsabilidades
adicionales:
Deteccin: bsqueda de complementos que se adhieran a los contratos admitidos por las aplicaciones
host.
Comunicacin: los complementos y las aplicaciones host deben poder comunicarse entre s ms all de
los lmites de aislamiento llamando a mtodos y pasando datos.
Control de versiones: garanta de que las aplicaciones host y los complementos puedan continuar
comunicndose cuando se creen nuevas versiones de cualquiera de ellos.
En ltima instancia, el desarrollo de un modelo de complementos robusto no es una tarea trivial. Por esta
razn, .NET Framework proporciona una infraestructura para generar modelos de complementos.
.Informacin general sobre el modelo de complementos de .NET Framework
El modelo de complementos de .NET Framework, que se encuentra en el espacio de nombres System.AddIn,
contiene un conjunto de tipos que permiten simplificar el desarrollo de la extensibilidad mediante
complementos. La unidad fundamental del modelo de complementos de .NET Framework es el contrato, que
define cmo se comunican entre s una aplicacin host y un complemento. Un contrato se expone a una
aplicacin host utilizando una vista del contrato que es especfica de la aplicacin host. De manera similar, se
expone al complemento una vista del contrato que es especfica del complemento. Se utiliza un adaptador para
que una aplicacin host y un complemento puedan comunicarse entre sus respectivas vistas del contrato. Los
contratos, las vistas y los adaptadores se conocen como segmentos y un conjunto de segmentos relacionados
constituye una canalizacin. Las canalizaciones son la base para que el modelo de complementos de .NET
Framework admita la deteccin, la activacin, el aislamiento de seguridad, el aislamiento de ejecucin
(utilizando tanto dominios de aplicacin como procesos), la comunicacin, la administracin de la duracin y el
control de versiones.
La suma de estas compatibilidades permite a los desarrolladores generar complementos que se integran con la
funcionalidad de una aplicacin host. Sin embargo, algunos escenarios requieren que las aplicaciones host
muestren las UIs proporcionadas por los complementos. Dado que cada tecnologa de presentacin de .NET
Framework tiene su propio modelo para implementar las UIs, el modelo de complementos de .NET Framework
no es compatible con ninguna tecnologa de presentacin en particular. En su lugar, WPF extiende el modelo de
complementos de .NET Framework con la compatibilidad de interfaz de usuario para los complementos.
Complementos de WPF
WPF, junto con el modelo de complementos de .NET Framework, permite manejar una amplia variedad de
escenarios que requieren que las aplicaciones host muestren las UIs de los complementos. En concreto, WPF
maneja estos escenarios con estos dos modelos de programacin:
1.
El complemento devuelve una interfaz de usuario. Un complemento devuelve una interfaz de usuario a
la aplicacin host mediante una llamada de mtodo, que se define en el contrato. Este escenario se utiliza
en los casos siguientes:
La apariencia de una interfaz de usuario devuelta por un complemento depende de los datos o
condiciones que solamente existen en tiempo de ejecucin, como informes generados
dinmicamente.
2.
El complemento es una interfaz de usuario. Un complemento es una interfaz de usuario, tal como lo
define el contrato. Este escenario se utiliza en los casos siguientes:
Estos escenarios requieren que se puedan pasar los objetos de la interfaz de usuario entre la aplicacin host y
los dominios de aplicacin del complemento. Puesto que el modelo de complementos de .NET Framework se
basa en la comunicacin remota para establecer la comunicacin entre los dominios de aplicacin, los objetos
que se pasen entre ellos debern poder usarse de forma remota.
Un objeto utilizable de forma remota es una instancia de una clase que cumple una o varias de las siguientes
condiciones:
Los tipos de interfaz de usuario de WPF no se pueden usar de forma remota. Para resolver el problema, WPF
extiende el modelo de complementos de .NET Framework para permitir que la interfaz de usuario de WPF
creada por complementos se muestre desde las aplicaciones host. Esta compatibilidad la proporciona WPF
mediante dos tipos: la interfaz INativeHandleContract y dos mtodos estticos que se implementan mediante la
clase FrameworkElementAdapters: ContractToViewAdapter y ViewToContractAdapter. A alto nivel, estos tipos y
mtodos se utilizan de la manera siguiente:
1.
WPF requiere que las UIs proporcionadas por complementos sean clases que deriven, directa o
indirectamente, de FrameworkElement, como formas, controles, controles de usuario, paneles de diseo y
pginas.
2.
Siempre que el contrato declare que se pasar una interfaz de usuario entre el complemento y la
aplicacin host, sta debe declararse como una interfaz INativeHandleContract (en lugar de un objeto
FrameworkElement);INativeHandleContract es una representacin utilizable de forma remota de la
interfaz de usuario del complemento que se puede pasar ms all de los lmites de aislamiento.
3.
Antes de que pase desde el dominio de aplicacin del complemento, un objeto FrameworkElement se
empaqueta como una interfaz INativeHandleContract llamando a ViewToContractAdapter.
4.
2.
El contrato debe implementar IContract y, para devolver una interfaz de usuario, el contrato debe
declarar un mtodo que devuelva un valor de tipo INativeHandleContract.
3.
La interfaz de usuario que se pasa entre el complemento y la aplicacin host debe derivarse, directa o
indirectamente, de FrameworkElement.
4.
6.
2.
3.
4.
El
complemento
se
debe
convertir
de
un
objeto
FrameworkElement
en
una
interfaz
El
complemento
se
debe
convertir
de
una
interfaz
INativeHandleContract
en
un
objeto
Los complementos proporcionan a menudo varias UIs para mostrar aplicaciones host. Por ejemplo, considere
un complemento que sea una interfaz de usuario que adems proporciona informacin de estado a la aplicacin
host, tambin como una interfaz de usuario. Un complemento de este tipo se puede implementar mediante una
combinacin de tcnicas de los modelos El complemento devuelve una interfaz de usuario y El complemento es
una interfaz de usuario.
Complementos y aplicaciones de explorador XAML
Hasta ahora, en los ejemplos, la aplicacin host era una aplicacin independiente instalada. Sin embargo, las
Aplicaciones del explorador XAML (XBAPs) tambin pueden hospedar complementos, aunque con los siguientes
requisitos adicionales de compilacin e implementacin:
El cdigo de la aplicacin XBAP para detectar y cargar los complementos debe usar la memoria cach
de aplicacin de ClickOnce para la aplicacin XBAP como ubicacin de la canalizacin y del
complemento.
Contrato
..\HostXBAP\Contracts\
Vista de complemento
..\HostXBAP\AddInViews\
..\HostXBAP\AddInSideAdapters\
..\HostXBAP\HostSideAdapters\
Complemento
..\HostXBAP\AddIns\WPFAddIn1
2.
El paso final es configurar el manifiesto de aplicacin de modo que incluya los archivos de ensamblado de
canalizacin y el archivo de ensamblado de complemento para la descarga. Los archivos deben ubicarse en
carpetas en la raz de la carpeta de la memoria cach de ClickOnce que la aplicacin XBAP ocupa. La
configuracin se puede realizar en Visual Studio siguiendo este procedimiento:
1.
Haga clic con el botn secundario del mouse en el proyecto XBAP, haga clic en Propiedades, haga clic
en Publicar y, a continuacin, haga clic en el botn Archivos de aplicacin.
2.
AddInStore.FindAddIns(Type, PipelineStoreLocation)
AddInStore.FindAddIns(Type, PipelineStoreLocation, array<String>[]()[])
AddInStore.Rebuild(PipelineStoreLocation)
AddInStore.Update(PipelineStoreLocation)
En el lado del complemento, WPF adquiere un identificador de ventana para la interfaz de usuario que
la aplicacin host mostrar. El identificador de ventana est encapsulado por una clase interna de
WPF que
deriva
de
HwndSource
implementa
INativeHandleContract.
ViewToContractAdapter devuelve una instancia de esta clase y se calculan sus referencias desde el
dominio de aplicacin del complemento al dominio de aplicacin de la aplicacin host.
En el lado de la aplicacin host, WPF reempaqueta HwndSource como una clase interna de WPF que
deriva de HwndHost y consume INativeHandleContract. ContractToViewAdapter devuelve una instancia
de esta clase a la aplicacin host.
HwndHost existe para mostrar las UIs, identificadas por identificadores de ventana, desde las UIs de WPF.
En resumen, INativeHandleContract, ViewToContractAdapter y ContractToViewAdapter existen para permitir
que el identificador de ventana de una interfaz de usuario de WPF pase de un complemento a una aplicacin
host, donde es encapsulado por HwndHost y muestra la interfaz de usuario de la aplicacin.
Nota:
Dado que la aplicacin host obtiene una clase HwndHost, no puede convertir el objeto devuelto por
ContractToViewAdapter en el tipo implementado por el complemento (por ejemplo, un control UserControl).
Debido a su naturaleza, la clase HwndHost tiene ciertas limitaciones que afectan al modo en que las
aplicaciones host la usan. Sin embargo, WPF extiende HwndHost con varias funciones para los escenarios de
complementos. Estas ventajas y limitaciones se describen a continuacin.
Ventajas de los complementos de WPF
Dado que las UIs de los complementos de WPF se muestran en las aplicaciones host utilizando una clase interna
que deriva de HwndHost, esas UIs estn restringidas por las funciones de HwndHost respecto a los servicios de
la interfaz de usuario de WPF, como el diseo, la representacin, el enlace de datos, los estilos, las plantillas y
Cumplimiento de los requisitos de accesibilidad para las UIs de los complementos que se muestran
desde las UIs de la aplicacin host.
Posibilidad de que las aplicaciones de WPF se ejecuten de forma segura en varios escenarios de
dominio de aplicacin.
Prevencin del acceso ilegal a los identificadores de ventana de la interfaz de usuario de los
complementos cuando stos se ejecutan con aislamiento de seguridad (es decir, un recinto de
seguridad de confianza parcial). Al llamar a ViewToContractAdapter, se garantiza esta seguridad:
Para el modelo de programacin "El complemento devuelve una interfaz de usuario", la nica
manera de pasar el identificador de ventana para una interfaz de usuario de complemento ms
all del lmite de aislamiento es llamar a ViewToContractAdapter.
Provisin de proteccin de ejecucin en varios dominios de aplicacin. Debido a las limitaciones con los
dominios de aplicacin, las excepciones no controladas que se producen en los dominios de aplicacin
del complemento hacen que se bloquee la aplicacin completa, aunque exista el lmite de aislamiento.
Sin embargo, WPF y el modelo de complementos de .NET Framework proporcionan una manera simple
de evitar este problema y mejorar la estabilidad de la aplicacin. Un complemento de WPF que
muestre una interfaz de usuario crea un objeto Dispatcher para el subproceso en el que se ejecuta el
dominio de aplicacin si la aplicacin host es una aplicacin de WPF. Para detectar todas las
excepciones no controladas que se produzcan en el dominio de aplicacin, controle el evento
UnhandledException del objeto Dispatcher del complemento de WPF. Puede obtener el objeto
Dispatcher mediante la propiedad CurrentDispatcher.
Las UIs de complementos que se muestran desde una aplicacin host no respetan el comportamiento
de recorte de la aplicacin host.
Los servicios de interfaz de usuario de una aplicacin host, como la herencia de recursos, el enlace de
datos y los comandos, no estn disponibles automticamente para las UIs de los complementos. Para
proporcionar estos servicios al complemento, es preciso actualizar la canalizacin.
Una interfaz de usuario de complemento no se puede girar, escalar, sesgar ni transformar de ninguna
otra manera.
El contenido de las UIs de complementos que se representa mediante operaciones de dibujo desde el
espacio de nombres System.Drawing puede incluir mezclas alfa. Sin embargo, tanto la interfaz de
usuario del complemento como la interfaz de usuario de la aplicacin host que la contiene deben ser
100% opacas; en otras palabras, la propiedad Opacity de ambas interfaces debe estar establecida en
1.
Si la propiedad AllowsTransparency de una ventana en la aplicacin host que contiene una interfaz de
usuario de complemento est establecida en true, el complemento ser invisible. Esto es cierto aunque
la interfaz de usuario del complemento sea 100% opaca (es decir, aunque la propiedad Opacity tenga
el valor 1).
Una interfaz de usuario de complemento debe aparecer encima de los dems elementos de WPF en la
misma ventana de nivel superior.
Los eventos del mouse generados para la interfaz de usuario del complemento no los recibe ni los
provoca la aplicacin host, y la propiedad IsMouseOver de la interfaz de usuario de la aplicacin host
tiene el valor false.
Cuando el foco se desplaza entre los controles de una interfaz de usuario de complemento, la
aplicacin host no recibe ni provoca los eventos GotFocus y LostFocus.
La parte de una aplicacin host que contiene una interfaz de usuario de complemento aparece en
blanco al imprimirse.
Todos los distribuidores (Dispatcher) creados por la interfaz de usuario del complemento se deben
cerrar manualmente antes de descargar el complemento propietario si la aplicacin host contina
ejecutndose. El contrato puede implementar mtodos que permiten a la aplicacin host sealar el
complemento antes de que ste se descargue, permitiendo que la interfaz de usuario del complemento
cierre sus distribuidores.
Ejemplo
Para crear un complemento que devuelve una interfaz de usuario de WPF se necesita un cdigo concreto para
cada segmento de la canalizacin, el complemento y la aplicacin host.
Implementar el segmento de canalizacin del contrato
El contrato debe definir un mtodo para devolver una interfaz de usuario y su valor devuelto debe ser de tipo
INativeHandleContract. El mtodo GetAddInUI del contrato IWPFAddInContract lo muestra en el cdigo
siguiente.
using System.AddIn.Contract; // IContract, INativeHandleContract
using System.AddIn.Pipeline; // AddInContractAttribute
namespace Contracts
{
/// <summary>
/// Defines the services that an add-in will provide to a host application
/// </summary>
[AddInContract]
public interface IWPFAddInContract : IContract
{
// Return a UI to the host application
INativeHandleContract GetAddInUI();
}
}
Implementar el segmento de canalizacin de la vista de complemento
Dado que el complemento implementa las UIs que proporciona como subclases de FrameworkElement, el
mtodo en la vista de complemento que guarda correlacin con IWPFAddInView.GetAddInUI debe devolver un
valor de tipo FrameworkElement. En el cdigo siguiente se muestra la vista de complemento del contrato,
implementada como una interfaz.
using System.AddIn.Pipeline; // AddInBaseAttribute
using System.Windows; // FrameworkElement
namespace AddInViews
{
/// <summary>
/// Defines the add-in's view of the contract
/// </summary>
[AddInBase]
public interface IWPFAddInView
{
// The add-in's implementation of this method will return
// a UI type that directly or indirectly derives from
// FrameworkElement.
FrameworkElement GetAddInUI();
}
}
Implementar el segmento de canalizacin del adaptador del complemento
El mtodo del contrato devuelve una interfaz INativeHandleContract, pero el complemento devuelve un objeto
FrameworkElement (segn lo especificado en la vista de complemento). Por consiguiente, el objeto
FrameworkElement se debe convertir en una interfaz INativeHandleContract antes de cruzar el lmite de
Este
trabajo
lo
realiza
el
adaptador
del
complemento
mediante
una
llamada
}
}
Implementar el segmento de canalizacin de la vista de host
Dado que la aplicacin host mostrar un objeto FrameworkElement, el mtodo en la vista de host que guarda
correlacin con IWPFAddInHostView.GetAddInUI debe devolver un valor de tipo FrameworkElement. En el
cdigo siguiente se muestra la vista de host del contrato, implementada como una interfaz.
using System.Windows; // FrameworkElement
namespace HostViews
{
/// <summary>
/// Defines the host's view of the add-in
/// </summary>
public interface IWPFAddInHostView
{
// The view returns as a class that directly or indirectly derives from
// FrameworkElement and can subsequently be displayed by the host
// application by embedding it as content or sub-content of a UI that is
// implemented by the host application.
FrameworkElement GetAddInUI();
}
}
Implementar el segmento de canalizacin del adaptador del host
El mtodo del contrato devuelve una interfaz INativeHandleContract, pero la aplicacin host espera un objeto
FrameworkElement
(segn
lo
especificado
por
la
vista
de
host).
Por
consiguiente,
la
interfaz
}
// Activate add-in with Internet zone security isolation
Collection<AddInToken> addInTokens = AddInStore.FindAddIns(typeof(IWPFAddInHostView),
appPath);
AddInToken wpfAddInToken = addInTokens[0];
this.wpfAddInHostView =
wpfAddInToken.Activate<IWPFAddInHostView>(AddInSecurityLevel.Internet);
// Get and display add-in UI
FrameworkElement addInUI = this.wpfAddInHostView.GetAddInUI();
this.addInUIHostGrid.Children.Add(addInUI);
Este
trabajo
lo
realiza
el
adaptador
del
complemento
mediante
una
llamada
FrameworkElement para poder "devolverlo". Por consiguiente, la vista de host debe derivar de una subclase de
continuacin,
el
adaptador
del
host
convierte
la
interfaz
INativeHandleContract
en
un
objeto
2.
En el cuadro de dilogo Nuevo proyecto, en el panel Tipos de proyecto, elija Visual Basic o Visual C#.
En el panel Plantillas, haga clic en Aplicacin de explorador WPF.
3.
Asigne un nombre de proyecto y haga clic en Aceptar para crear el nuevo proyecto.
La plantilla de proyecto Aplicacin de explorador WPF crea un proyecto de aplicacin XBAP que incluye lo
siguiente:
Un manifiesto de implementacin. Este archivo contiene la informacin que ClickOnce utiliza para
implementar la aplicacin y tiene la extensin .xbap.
Publique las XBAPs en un servidor web (Microsoft Internet Information Services (IIS) o posterior). No es
necesario instalar .NET Framework en el servidor web, pero s debe registrar las extensiones de archivo y los
tipos Extensiones multipropsito de correo Internet (MIME) de WPF.
Para preparar la aplicacin XBAP para la implementacin, copie el archivo .exe y los manifiestos asociados en el
servidor web. Cree un hipervnculo en una pgina web para navegar al manifiesto de implementacin. Cuando
el usuario hace clic en el vnculo y navega al archivo .xbap, ClickOnce administra automticamente los
mecanismos de descarga e inicio de la aplicacin.
Borrar aplicaciones XBAP almacenadas en memoria cach
En algunas situaciones, despus de volver a generar e iniciar la aplicacin XBAP, es posible que se inicie una
versin anterior de la aplicacin XBAP. Por ejemplo, esto puede pasar cuando el nmero de versin de
ensamblado de la aplicacin XBAP es esttico y se inicia la aplicacin XBAP desde la lnea de comandos. En este
caso, dado que el nmero de versin entre la versin almacenada en memoria cach (la versin que se inici
previamente) y la nueva versin sigue siendo el mismo, no se descarga la nueva versin de la aplicacin XBAP
sino la versin almacenada en memoria cach.
En estas situaciones, puede quitar la versin almacenada en memoria cach utilizando el comando Mage (se
instala con Windows SDK) desde el smbolo del sistema:
Mage.exe -cc
De manera estndar, un WMCequipo personal (PC) se puede utilizar para ver y reproducir elementos
multimedia digitales. Esto se denomina la experiencia del usuario a corta distancia, porque los usuarios
manejan WMC desde el PC, utilizando el mouse, el teclado y el monitor.
Sin embargo, un PC de WMC se puede configurar para admitir el control remoto o acciones del teclado remotas.
En esta situacin, los usuarios no tienen que encontrarse ante el PC de WMC para manejarlo. Esto se denomina
experiencia del usuario a larga distancia, y corresponde a configuraciones de WMC que incluyen monitores de
pantalla grande, as como hardware tradicional de entretenimiento domstico, como televisores y sistemas de
sonido.
La funcionalidad bsica que WMC ofrece est compuesta de un conjunto de aplicaciones que permiten
administrar y reproducir elementos multimedia digitales. Sin embargo, puede utilizar WPF para crear sus
propias aplicaciones personalizadas para las versiones Windows Vista de WMC.
En este tema se proporciona una introduccin a la programacin de aplicaciones de WPF para WMC y se
abarcan los temas siguientes:
wordgamewmc.exe. La XBAP.
wordgamewmc.exe.manifest. El manifiesto de aplicacin de ClickOnce.
wordgamewmc.xbap. El manifiesto de implementacin de ClickOnce.
Las XBAPs se inician utilizando ClickOnce, lo que exige configurar la aplicacin con los archivos de manifiesto de
implementacin y aplicacin. En particular, una XBAP se inicia cuando se examina su archivo .xbap o se hace
doble clic en l. Cuando se inicia, el comportamiento predeterminado es que ClickOnce descargue la aplicacin
en nombre de WPF, despus de lo cual WPF inicia Internet Explorer y navega en l hasta la aplicacin, como se
muestra en la ilustracin siguiente:
Sin embargo, para iniciar una aplicacin de WMC, el usuario abre o hace doble clic en archivo de vnculo (.mcl)
de WMC. Un archivo .mcl es un archivo de configuracin XML que se configura en Windows para que lo abra el
host de WMC (ehshell.exe) cuando se examina o se hace doble clic en l (consulte WMC SDK).
Nota:
.Los archivos .mcl son cmodos durante el proceso de programacin, pero no se recomiendan como
Nota:
Si desea que WMC hospede una aplicacin de XAML dinmico, debe configurar el archivo .mcl con un
archivo .xaml, de este modo:
<application
url="http://localhost/loosexamlapplication/loosexamlpage.xaml" />
Sin ningn cambio de la propia XBAP y con la adicin de un solo archivo de configuracin, WMC puede hospedar
una aplicacin de WPF hospedada por explorador, tal cual.
Sin embargo, la experiencia del usuario de WMC es bastante concreta y, por motivos de coherencia y estilo, las
aplicaciones XBAP de WMC deben disearse para integrarse con esta experiencia del usuario de WMC. En el
resto de este tema se abarcan los aspectos fundamentales de la experiencia de usuario de WMC y cmo
generar XBAPs que tengan en cuenta dicha experiencia.
Experiencia de usuario de WMC
Proporcionar una experiencia del usuario coherente es una parte fundamental de la programacin de cualquier
aplicacin. Con respecto a los usuarios de WMC, la aplicacin debe intentar ser coherente en los aspectos
siguientes:
Aunque en WMC SDK encontrar una explicacin detallada sobre WMC, en los temas siguientes se proporciona
informacin general de alto nivel.
Tema
Como se puede ver en la siguiente ilustracin, el tema de WMC tiene varios elementos diferenciadores:
El ms distintivo de ellos es un fondo azul vtreo y fuentes redondeadas grandes de color claro. El resultado es
crear un aspecto que pueda ser discernido con facilidad tanto por los usuarios a corta distancia, que estn
delante mismo del monitor, y a larga distancia, que pueden estar alejados del televisor. Aunque las aplicaciones
de WPF deben seguir este enfoque general con respecto al aspecto, WMC no expone de manera nativa esta
informacin para que la utilicen las aplicaciones de WPF. Afortunadamente, WPF s proporciona una
infraestructura enriquecida para aplicar estilos y temas que se puede aprovechar para reproducir con facilidad
el aspecto de WMC, si se desea. Como alternativa, puede utilizar WPF para crear una experiencia del usuario
completamente nueva y visualmente enriquecida, aunque debe tener presentes las consideraciones de diseo y
navegacin.
Por ejemplo, para crear un fondo de estilo WMC para las pginas, puede proceder como sigue:
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="HomePage.xaml">
<!--MediaCenterThemes.xaml-->
<Application.Resources>
<LinearGradientBrush x:Key="PageGlassyBackground" StartPoint="0,0.5"
EndPoint="1,0.5">
<GradientStop Color="#ff2B6680" Offset="1.5" />
<GradientStop Color="#569dc2" Offset="0" />
</LinearGradientBrush>
...
</Application.Resources>
</Application>
Dado que los temas suelen estar compuestos de ms de un elemento, puede ser conveniente utilizar un
diccionario de recursos personalizado para encapsular los estilos del tema de WMC:
<ResourceDictionary>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" />
<LinearGradientBrush x:Key="PageGlassyBackground" StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="#ff2B6680" Offset="1.5" />
<GradientStop Color="#569dc2" Offset="0" />
</LinearGradientBrush>
...
</ResourceDictionary>
Para incorporar un diccionario de recursos a una aplicacin, se configura el elemento Application.Resources
de la definicin de aplicacin de manera que haga referencia al archivo del diccionario de recursos .xaml:
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml">
<!--MediaCenterThemes.xaml-->
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
WMC no le impide programar temas de aplicacin que incorporan los elementos especficos de la aplicacin y de
la marca. Sin embargo, existen varios aspectos del tema de una aplicacin que deben tenerse en cuenta al
disear cualquier aplicacin para lograr la experiencia del usuario de WMC, que incluyen:
Colores seguros para televisin: no utilice colores luminosos que sean susceptibles a mostrarse
borrosos (p. ej., verde, rojo).
Contraste: para que el texto se distinga visualmente del fondo, asegrese de que la eleccin de los
colores de primer plano y de fondo de los elementos visuales tenga un nivel adecuado de contraste.
Fuentes: puede mejorar la legibilidad utilizando fuentes de mayor tamao sin enlaces. Adems, quitar
las palabras innecesarias del contenido puede ayudar a crear reas de texto ms fciles de leer.
Consulte WMC SDK para obtener informacin detallada sobre los temas de aplicacin de WMC.
Diseo
Un problema puede no resultar evidente a primera vista se produce cuando un usuario desplaza el puntero del
mouse sobre el host de WMC, lo que hace que el host de WMC muestre elementos de la interfaz de usuario
adicionales para la navegacin controlada por mouse, como se muestra en la ilustracin siguiente:
En esta ilustracin, puede ver las partes superior izquierda e inferior derecha de la interfaz de usuario de la
aplicacin, cubiertas por el marco de navegacin. En esta situacin, puede actualizar el diseo de la interfaz de
usuario para que tenga en cuenta la interfaz de usuario de navegacin. Para WordGame!, esto implic mover el
ttulo de la aplicacin a la derecha de la interfaz de usuario y agregar una fila de 50 pxel de alto a la parte
inferior del elemento Grid que hospeda el contenido de la pgina principal:
<Grid>
...
Por esta razn, las XBAPs para WMC tienen que ser sensibles a los distintos comportamientos de diseo y
coherencia de WMC.
Los aspectos de diseo fundamentales que debe tener en cuenta son:
Diseo de la aplicacin: el diseo de las aplicaciones debe ser simple y coherente, para facilitar al
usuario el desarrollo y la conservacin de la familiaridad con la interfaz de usuario de su aplicacin.
Diseo de WMC: el diseo de las aplicaciones debe, siempre que sea prctico, conservar la
coherencia con la experiencia del usuario de WMC general. Esto permite que los usuarios que ya estn
familiarizados con WMC se sientan cmodos antes con la aplicacin.
Vdeo: si la aplicacin muestra vdeo mediante las API administradas de WMC, WMC reproducir el
vdeo en la parte inferior izquierda de la pantalla. Por consiguiente, debe tenerlo en cuenta al disear
la interfaz de usuario.
Resolucin: la interfaz de usuario y el diseo de la aplicacin deben estar destinados para una
resolucin de 1024 x 768. WPF ofrece compatibilidad de diseo para a ayudarlo a disear la interfaz de
usuario para 1024 x 768 y asegurarse de que el diseo se conserve al cambiar el tamao de la interfaz
de usuario.
Navegacin
En esencia, el tema y el diseo rigen cmo se organizan los controles que componen la interfaz de usuario de la
aplicacin. La navegacin, por otro lado, dicta cmo los usuarios tienen acceso a los controles y se mueven
entre ellos.
El control que recibe los datos proporcionados por el usuario es el que tiene el foco. Para llevar el foco a un
control concreto cuando se muestra una pgina de la aplicacin XBAP, puede utilizar el marcado:
<!-- Set focus on guess character text box -->
<Page ... FocusManager.FocusedElement="{Binding ElementName=guessedChar}">
...
</Page>
Esto se debe hacer para admitir los modos de manejo a corta y larga distancia.
Para permitir a los usuarios navegar por los controles de una aplicacin de WMC en los modos de corta y larga
distancia, la aplicacin debe administrar la navegacin mediante un mouse, un teclado (conectado o remoto) y
control remoto. De manera predeterminada, la navegacin con el mouse y el teclado es igual que en cualquier
aplicacin de WPF, e incluye:
Utilizar la propiedad IsCancel de un botn para especificar que se hace clic en l de forma
predeterminada cuando se presiona la tecla ESC.
Para admitir el control remoto, es preciso admitir la navegacin direccional, lo que significa permitir a los
usuarios mover el foco de los controles haciendo clic en los botones arriba, abajo, izquierda y derecha del
dispositivo de control remoto. No es necesario escribir ningn cdigo especial para admitir la navegacin
direccional, siempre que utilice un subconjunto concreto de controles de WPF.
Actualizar los controles de WPF para WMC
Aunque WPF proporciona gran cantidad de controles, slo un subconjunto de ellos es adecuado para su uso en
las aplicaciones de WMC de manera predeterminada. El factor determinante es si es posible navegar hasta
ellos, manipularlos y salir de ellos mediante un dispositivo de control remoto. En la ilustracin siguiente se
muestra un subconjunto de controles de WPF que admiten datos proporcionados desde un dispositivo de control
remoto (mediante los estilos de WMC):
Estas limitaciones no impiden el uso de otros controles de WPF, aunque deber realizar tareas adicionales para
que funcionen con WMC. Por ejemplo, tomemos el control Slider, que se muestra hospedado en WMC en la
ilustracin siguiente:
De manera predeterminada, con un mouse, un teclado o un dispositivo de control remoto es posible mostrar un
Slider o navegar hasta l. Sin embargo, no es posible salir de Slider mediante un dispositivo de control remoto:
Slider interpreta las pulsaciones en los botones arriba, abajo, izquierda y derecha del dispositivo de control
remoto como intentos de aumentar o disminuir el valor de Slider.
En estas situaciones, una solucin consiste en crear un control compuesto que contenga el control deseado y,
adems, los controles adicionales aptos para el control remoto que permitan manipularlo con facilidad. Por
ejemplo, Slider se puede utilizar con dos botones, uno para disminuir el valor de Slider y otro para incrementar
el valor de Slider, mediante el cdigo siguiente:
<Page x:Class="SliderPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Custom Slider -->
<StackPanel Margin="50" Orientation="Horizontal" VerticalAlignment="Top">
<Button
Name="decrementButton"
Click="decrementButton_Click"
Margin="10"
FontSize="10"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Width="40" Height="40">
</Button>
<Slider
Name="slider"
Esto se implementa como la clase SoftKeyboardTextBox del ensamblado Keyboard.dll que se suministra con
el ejemplo y reside en el espacio de nombres MCEControls. Para utilizarlo, proceda como sigue:
1.
2.
3.
Sin embargo, el aspecto de un cuadro de mensaje estndar de WPF no es coherente con la experiencia del
usuario de WMC. Afortunadamente, las API administradas de WMC proporcionan su propio cuadro de mensajes
de tipo WMC que puede utilizar con cdigo como el siguiente:
using Microsoft.MediaCenter;
...
// Get media center host and show dialog box
MediaCenterEnvironment mce =
Microsoft.MediaCenter.Hosting.AddInHost.Current.MediaCenterEnvironment;
mce.Dialog(msg, "WordGame!", DialogButtons.Ok, 1000, true);
Este cdigo hace que se muestre un cuadro de dilogo de WMC como ste:
Es conveniente consultar WMC SDK para obtener conocimientos en profundidad sobre las API administradas de
WMC.
Nota:
No se puede ejecutar una XBAP que hace referencia a las API administradas de WMC a menos que la XBAP
se hospede en WMC.
Programar con Visual Studio
Hasta ahora, en este tema se han abarcado los problemas bsicos de programacin que deber tener en cuenta
al crear XBAPs para WMC, lo que incluye:
stos son los problemas que probablemente necesitar abordar en cada XBAP que genere para WMC. En lugar
de volver a crear estos elementos personalmente cada vez que genere una XBAP para WMC, puede utilizar la
plantilla de proyecto Media Center Application (WPF) para Microsoft Visual Studio 2005 que se instala con WMC
SDK.
Nota:
Las plantillas de proyecto de WMC nicamente se instalan si se instalan Visual Studio 2005 y tambin
"Fidalgo".
La plantilla de proyecto Media Center Application (WPF) crea un proyecto de Visual Studio 2005 que incluye
estos elementos de manera predeterminada.
Para crear una nueva aplicacin con Media Center Application (WPF):
1.
2.
Elija Microsoft Visual Studio | Archivo | Nuevo | Proyecto | Visual C# | .NET Framework 3.0 |
Media Center Application (WPF).
Un archivo readme.txt, que incluye texto til sobre la compilacin y depuracin de XBAPs para WPF.
Referencias a los ensamblados administrados de WMC.
Un archivo MediaCenterTheme.xaml, que es un diccionario de recursos que contiene un conjunto
completo de estilos de WMC que, de manera predeterminada, se aplican a la pgina predeterminada,
Page1.xaml.
Observe que existe una plantilla de proyecto equivalente para Microsoft Visual Basic.
Depurar proyectos
Para depurar una XBAP dentro del host de WMC en Visual Studio 2005, necesita hacer lo siguiente:
1.
En el Explorador de soluciones, haga clic con el botn secundario del mouse en el proyecto y elija
Propiedades | Depurar.
2.
3.
4.
Ejecute la aplicacin, para ello, elija Microsoft Visual Studio | Depurar | Iniciar depuracin (o
presione F5).
5.
Haga
doble
clic
en
el
archivo
.mcl
que
se
genera
durante
el
proceso
de
compilacin
(\bin\debug\assemblyname.mcl).
La aplicacin especificada en el archivo .mcl se iniciar y hospedar en WMC.
Instalar una aplicacin de WPF para WMC
Una de las ventajas de utilizar WMC es su capacidad de ayudar a crear aplicaciones de Microsoft Windows
Installer (archivos .msi). .Los archivos .msi constituyen una manera til de distribuir la aplicacin de WPF a los
equipos del cliente WMC.
El procedimiento siguiente se ha utilizado para crear una aplicacin de Windows Installer simple para
WordGame!:
1.
En Visual Studio 2005, haga clic con el botn secundario del mouse en la solucin de XBAP en el
Explorador de soluciones y seleccione Agregar | Nuevo proyecto.
2.
implementacin.
3.
4.
Haga clic con el botn secundario en el nuevo proyecto de Windows Installer, elija Agregar | Archivo
y elija los archivos siguientes:
1.
WordGameWMC.mcl
2.
WordGameWMC.exe
3.
WordGameWMC.exe.manifest
4.
WordGameWMC.xbap
5.
WordList.txt
6.
Keyboard.dll
6.
En la lista de archivos, haga clic con el botn secundario del mouse y seleccione Crear acceso
directo a Escritorio del usuario.
7.
8.
Para los archivos de estos tipos, el host de Windows Presentation Foundation (WPF):
Inicia el controlador HTML registrado para hospedar el contenido de Windows Presentation Foundation
(WPF).
Carga las versiones correctas de los ensamblados necesarios de common language runtime (CLR) y
Windows Presentation Foundation (WPF).
Se asegura de que se apliquen los niveles de permisos adecuados para la zona de implementacin.
En este tema se describen los parmetros de lnea de comandos que se utilizar con PresentationHost.exe
Descripcin
filename
Ruta de acceso del archivo que se va a activar. Tambin puede ser un URI.
-debug
-debugSecurityZoneURL
<url>
-embedding
-event <nombreEvento>
Escenarios
Controlador de ncleo
PresentationHost.exe example.xbap
Controlador MIME
2.6.4.1. IEnumRAWINPUTDEVICE
Esta interfaz enumera los dispositivos de entrada sin formato y slo la utiliza PresentationHost.exe.
Miembros
Miembro
Descripcin
IEnumRAWINPUTDEVIC:Next
Enumera
los
elementos
celt
siguientes
(es
decir,
las
estructuras
IEnumRAWINPUTDEVIC:Reset
IEnumRAWINPUTDEVIC:Clone
2.6.4.2. IWpfHostSupport
Las
aplicaciones
que
hospedan
contenido
de
Windows
Presentation
Foundation
(WPF)
mediante
PresentationHost.exe implementan esta interfaz para proporcionar un punto de integracin entre el host y
PresentationHost.exe.
Comentarios
Las aplicaciones de Win32 como los exploradores web pueden hospedar contenido de WPF, incluidas las
Aplicaciones del explorador XAML (XBAPs) y XAML dinmico. Para hospedar contenido de WPF, las aplicaciones
de Win32 crean una instancia del control WebBrowser. Para hospedarse, WPF crea una instancia de
PresentationHost.exe, que proporciona el contenido de WPF hospedado al host para mostrarlo en el control
WebBrowser.
La integracin habilitada por IWpfHostSupport permite a PresentationHost.exe:
Detectar y registrar los dispositivos de entrada sin formato (dispositivos de interfaz de usuario) en los
que la aplicacin host est interesada.
Recibir los mensajes de entrada de los dispositivos de entrada sin formato registrados y reenve los
mensajes adecuados a la aplicacin host.
Consultar la aplicacin host para obtener las interfaces de usuario personalizadas de progreso y
errores.
Miembros
Miembro
Descripcin
GetRawInputDevices
FilterInputMessage
GetCustomUI
MSBuild:
el
sistema
de
compilacin
de
.NET
situado
en
el
espacio
de
nombres
Microsoft.Build.Tasks.Windows.
Esta aplicacin se genera con el compilador de C#, csc.exe, desde un smbolo del sistema, como en el ejemplo
siguiente:
csc.exe
/out:WPFApplication.exe
/target:winexe
app.cs mainwindow.cs
/reference:"C:\Program Files\Reference
Assemblies\Microsoft\Framework\v3.0\presentationframework.dll"
/reference:"C:\Program Files\Reference
Assemblies\Microsoft\Framework\v3.0\windowsbase.dll"
/reference:"C:\Program Files\Reference
Assemblies\Microsoft\Framework\v3.0\presentationcore.dll"
En este ejemplo:
Para generar aplicaciones ms complejas se puede utilizar la compilacin desde la lnea de comandos, aunque
el compilador no admite aplicaciones de WPF que incluyan cdigo fuente Lenguaje de marcado de aplicaciones
extensible (XAML). Asimismo, la compilacin desde la lnea de comandos no admite el conjunto completo de
requisitos de compilacin de las aplicaciones de WPF tpicas, incluida la administracin de la configuracin y la
generacin de manifiestos ClickOnce. Para admitir stos y otros requisitos de compilacin ms complejos, WPF
se integra con MSBuild y extiende su funcionalidad.
Generar una aplicacin de WPF mediante MSBuild
MSBuild es una tecnologa robusta y extensible que se introdujo con .NET Framework. El ncleo de la tecnologa
MSBuild est implementado en todos los ensamblados que se describen en la tabla siguiente.
Ensamblado
Descripcin
Microsoft.Build.Engine.dll
Microsoft.Build.Tasks.dll
Microsoft.Build.Utilities.dll
Microsoft.Build.Framework.dll
Microsoft.Build.Conversion.dll
Requisitos de compilacin.
Esta informacin se empaqueta en archivos de XML compatibles con el esquema de MSBuild personalizado para
que MSBuild pueda procesarla. Estos archivos se denominan archivos de proyecto de MSBuild. A continuacin,
se incluye un archivo de proyecto de MSBuild para una versin de la aplicacin de WPF que generamos
previamente mediante un compilador de la lnea de comandos, al que se incorporaron archivos de cdigo fuente
de Lenguaje de marcado de aplicaciones extensible (XAML).
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AssemblyName>WPFApplication</AssemblyName>
<OutputType>winexe</OutputType>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml" />
<Compile Include="App.xaml.cs" />
<Page Include="MainWindow.xaml" />
<Compile Include="MainWindow.xaml.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />
</Project>
Este ejemplo contiene los elementos que son comunes a la mayora de los archivos de proyecto de MSBuild,
incluida la etiqueta Project, las propiedades, los elementos, los destinos y las tareas.
El elemento Project
Segn se especifica en el esquema de archivo de proyecto de MSBuild, un archivo de proyecto de MSBuild es un
archivo XML con Project como elemento de nivel superior:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
</Project>
El elemento Project es donde el motor de MSBuild inicia el procesamiento de un archivo de proyecto. Para
especificar la versin de MSBuild utilizada para el archivo de proyecto de MSBuild, se proporciona una
declaracin de espacio de nombres XML adecuada.
Propiedades
Las propiedades son variables que se utilizan para configurar los proyectos de MSBuild y proporcionar
informacin especfica de la compilacin al motor de MSBuild. Las propiedades se incluyen en elementos
PropertyGroup, como se muestra en el ejemplo siguiente.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AssemblyName>WPFApplication</AssemblyName>
<OutputType>winexe</OutputType>
</PropertyGroup>
...
</Project>
Algunas propiedades, como AssemblyName y OutputType, son comunes a todos los tipos de aplicacin y se
describen en Propiedades comunes de proyectos de MSBuild. En la tabla siguiente se muestran las propiedades
de MSBuild especficas de WPF.
Propiedad
Descripcin
OutputType
HostInBrowser
Especifica si XBAP se instala en el cliente. Install puede ser true o false, y tiene el
valor contrario de HostInBrowser.
GenerateManifests
Elementos
Los elementos son entradas de MSBuild que procesa el motor de MSBuild durante el proceso de compilacin.
Los elementos se incluyen dentro de un elemento ItemGroup.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<ItemGroup>
<Reference Include="System" />
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml" />
<Compile Include="App.xaml.cs" />
<Page Include="MainWindow.xaml" />
<Compile Include="MainWindow.xaml.cs" />
</ItemGroup>
...
</Project>
El tipo de un elemento se puede configurar con metadatos; en el ejemplo anterior, las referencias de
ensamblado se configuran como elementos Reference y los archivos de cdigo fuente se configuran como
elementos Compile. Los elementos Reference y Compile son comunes a todas las aplicaciones de .NET
Framework.
En la tabla siguiente se muestran los elementos de MSBuild especficos de WPF.
Propiedad
Descripcin
ApplicationDefinition
Page
Page (System.Windows.Controls.Page).
ResourceDictionary (System.Windows.ResourceDictionary).
FlowDocument (System.Windows.Documents.FlowDocument).
UserControl (System.Windows.Controls.UserControl).
Resource
Content
Destinos
Los destinos determinan cmo se generan los proyectos y dependen de las propiedades y los elementos. Una
aplicacin de WPF debe tener un destino especfico del lenguaje y un destino especfico de WPF.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />
</Project>
Los destinos son archivos independientes que terminan con la extensin .targets. Los archivos de destino que
se incluyen con .NET Framework se instalan en la ubicacin siguiente:
%WINDIR%\Microsoft.NET\Framework\vX.X.X
El destino especfico del lenguaje genera cdigo fuente especfico del lenguaje. El destino especfico del
lenguaje de C# es Microsoft.CSharp.targets y Microsoft.VisualBasic.targets para Visual Basic. Ambos destinos
se derivan y extienden el destino Microsoft.Common.targets, que realiza la mayora del trabajo de compilacin
comn independiente del lenguaje. Para obtener ms informacin sobre los destinos comunes y especficos del
lenguaje de MSBuild.
El destino Microsoft.WinFX.targets realiza el trabajo de compilacin especfico de WPF. Entre sus tareas se
incluye la compilacin del marcado XAML, la generacin de manifiestos para las aplicaciones XBAP y el
procesamiento de los recursos y archivos de contenido de WPF.
Tareas
Una tarea es una clase que realiza una accin de compilacin especfica. Los destinos combinan una o varias
tareas para definir un proceso de compilacin; cuando MSBuild procesa un destino, ejecuta las tareas incluidas
en l. Las tareas utilizadas por los destinos comunes y especficos del lenguaje se implementan mediante el
ensamblado Microsoft.Build.Tasks, y las tareas especficas de WPF se implementan mediante el ensamblado
PresentationBuildTasks.
Los destinos proporcionan compatibilidad para generar todas las aplicaciones de WPF estndar. Tambin es
posible utilizar combinaciones alternativas de tareas para implementar un comportamiento de compilacin
personalizado. Por ejemplo, la tarea MSBuild GetWinFXPath siguiente se utiliza para detectar la ruta de acceso
nativa del motor en tiempo de ejecucin de .NET Framework, que depende de si la tarea se ejecuta en un
procesador de 64 bits:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask
TaskName="Microsoft.Build.Tasks.Windows.GetWinFXPath"
AssemblyFile="C:\Program Files\Reference
El archivo de proyecto es ms grande que el de los ejemplos anteriores, debido en parte a varias propiedades
adicionales. Sin embargo, la informacin adicional es especfica de Visual Studio e incluye lo siguiente:
La asociacin entre los archivos de cdigo fuente relacionados se realiza utilizando los metadatos
DependentUpon y SubType:
<Project ... >
...
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="Window1.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Window1.xaml.cs">
<DependentUpon>Window1.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
...
</Project>
En este proyecto, App.xaml (archivo de marcado) est asociado a App.xaml.cs (archivo de cdigo subyacente),
y Window1.xaml (archivo de marcado) est asociado a Window1.xaml.cs (archivo de cdigo subyacente).
Administracin de las propiedades, recursos y configuracin del proyecto predeterminados
Visual Studio permite modificar visualmente las propiedades de un proyecto escrito en Visual Studio. La
mayora de estas propiedades afectan al proceso de compilacin y se almacenan en el archivo de proyecto de
Visual Studio administrado por Visual Studio. Las plantillas de proyecto de Windows Presentation Foundation
(WPF) generan tambin archivos para proporcionar compatibilidad con los recursos y valores con
establecimiento inflexible de tipos. Todo esto se muestra en la siguiente ilustracin:
msbuild.exe msbuildprojectfile.proj
Generar un proyecto especfico del lenguaje generado por Visual Studio
Los archivos de proyecto de MSBuild especficos del lenguaje generados por Visual Studio:
msbuild.exe VSGeneratedProjectFileForCSharp.csproj
A continuacin, se muestra cmo generar un proyecto de Visual Basic desde el smbolo del sistema:
msbuild.exe VSGeneratedProjectFileForVisualBasic.vbproj
Generar una solucin generada por Visual Studio
msbuild.exe generar tambin archivos de solucin (.sln) generados por Visual Studio:
Al realizar alguna de estas operaciones para un proyecto o solucin, Visual Studio ejecuta msbuild.exe para
generar los archivos MSBuild correspondientes.
Canalizacin de compilacin de Windows Presentation Foundation
Cuando se genera un proyecto de WPF, se invoca la combinacin de destinos especficos del lenguaje y de WPF.
El proceso de ejecucin de estos destinos se denomina canalizacin de compilacin y los pasos principales se
muestran en la siguiente ilustracin.
.NET Framework.
Los directorios de Windows SDK.
La ubicacin de los ensamblados de referencia de WPF.
La propiedad de las rutas de bsqueda de ensamblados.
2.
3.
Se crea una representacin de CodeDOM de una nueva clase parcial y se copia a la carpeta
obj\Release.
Adems, se genera un archivo de cdigo especfico del lenguaje para cada archivo XAML. Por ejemplo, para una
pgina Page1.xaml de un proyecto escrito en Visual Basic se genera un archivo Page1.g.vb; para una pgina
Page1.xaml de un proyecto escrito en C# se genera un archivo Page1.g.cs. ".g" en el nombre de archivo indica
que el archivo es cdigo generado que tiene una declaracin de clase parcial para el elemento de nivel superior
del archivo de marcado (como Page o Window). La clase se declara con el modificador partial de C# (Extends
en Visual Basic) para indicar que es otra declaracin de la clase en otro lugar, normalmente en el archivo
Page1.xaml.cs de cdigo subyacente.
La clase parcial se extiende desde la clase base correspondiente (como Page para una pgina) e implementa la
interfaz System.Windows.Markup.IComponentConnector. La interfaz IComponentConnector tiene mtodos que
inicializan un componente y conectan los nombres y eventos en elementos en su contenido. Por consiguiente, el
archivo de cdigo generado tiene una implementacin de mtodos como la siguiente:
public void InitializeComponent()
{
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater =
new System.Uri(
"window1.xaml",
System.UriKind.RelativeOrAbsolute);
System.Windows.Application.LoadComponent(this, resourceLocater);
}
De forma predeterminada, la compilacin del marcado se ejecuta en el mismo AppDomain que el motor de
MSBuild. Esto proporciona una mejora del rendimiento importante. Este comportamiento se activa o desactiva
con la propiedad AlwaysCompileMarkupFilesInSeparateDomain y tiene la ventaja de que todos los ensamblados
de referencia se descargan al descargar el AppDomain independiente.
Generacin del marcado: Paso 2
No todas las pginas XAML se generan en el paso 1 de la compilacin de marcado. Los archivos XAML que
tienen referencias de tipos definidos localmente (referencias a tipos definidos en el cdigo en otro lugar del
mismo proyecto) no se generan en este momento. Esto se debe a que estos tipos definidos localmente slo
existen en el cdigo fuente y an no estn generados. Para determinar esto, el analizador utiliza heurstica que
El archivo es la unidad ms pequea en la que el sistema de compilacin detecta un cambio. Por tanto,
para un archivo de cdigo, el sistema de compilacin no puede determinar si se ha cambiado un tipo o
se ha agregado cdigo. Lo mismo se aplica a los archivos de proyecto.
El mecanismo de compilacin incremental debe saber que una pgina XAML define una clase o utiliza
otras clases.
Si un archivo de cdigo cambia, vuelva a generar todas las pginas con referencias de tipos definidos
localmente.
Si XAML se declara como Page en el proyecto: si XAML no tiene referencias de tipos definidos
localmente, vuelva a generar ese XAML adems de todas las pginas XAML con referencias
locales; si XAML tiene referencias locales, vuelva a generar todas las pginas XAML con referencias
locales.
De lo contrario, vuelva a generar todas las pginas XAML con referencias locales.
Si un archivo de proyecto cambia: aplique todas las reglas anteriores y determine lo que tiene que
volver a generar. Los cambios en las propiedades siguientes desencadenan una recompilacin
completa: AssemblyName, IntermediateOutputPath, RootNamespace y HostInBrowser.
Implementacin de XCopy.
Microsoft Windows Installer.
Implementacin de ClickOnce.
Windows Conexin a escritorio remoto (RDC).
La tecnologa de implementacin que se utiliza para implementar una aplicacin de WPF depende del tipo de
esta ltima. En WPF, hay tres tipos de aplicacin:
Aplicaciones independientes.
Aplicaciones del explorador XAML (XBAPs).
Pginas Lenguaje de marcado de aplicaciones extensible (XAML) hospedadas por explorador.
Una aplicacin no requiere la integracin en el shell (acceso directo del men de Inicio, icono de
escritorio, etc.).
Aunque XCopy es adecuado para escenarios de implementacin simples, presenta limitaciones cuando se
requieren funciones de implementacin ms complejas. En particular, al utilizar Xcopy se provoca una
sobrecarga al crear, ejecutar y mantener los scripts necesarios para administrar la implementacin de una
manera robusta. Adems, XCopy no admite el control de versiones, la desinstalacin ni la reversin.
Microsoft Windows Installer
Windows Installer permite empaquetar las aplicaciones como aplicaciones ejecutables autnomas que se
pueden distribuir con facilidad a los clientes y ejecutar. Adems, Windows Installer se instala con Windows y
habilita la integracin con el escritorio, el men Inicio, y el panel de control Agregar o quitar programas.
Windows Installer simplifica la instalacin y desinstalacin de aplicaciones, pero no proporciona los medios para
asegurarse de que las aplicaciones instaladas se mantengan actualizadas desde el punto de vista de su versin.
Implementacin ClickOnce
ClickOnce habilita la implementacin de aplicaciones de tipo web para aplicaciones no web: las aplicaciones se
publican e inician desde servidores web. Aunque ClickOnce no admite la gama completa de caractersticas de
cliente que s poseen las aplicaciones instaladas con Windows Installer, admite un subconjunto que incluye lo
siguiente:
Integracin con el men Inicio y el panel de control Agregar o quitar programas, para aplicaciones
independientes.
Estos archivos se crean al generar una XBAP mediante MSBuild. Al igual que las pginas XAML slo de marcado,
las XBAPs se suelen publicar en un servidor web y se exploran mediante Internet Explorer.
Las XBAPs se pueden implementar en clientes utilizando XCopy o Windows Installer. Sin embargo, al
implementar XBAPs de esta manera deben tenerse en cuenta dos cosas:
1.
2.
La XBAP se ejecuta con permisos de plena confianza, un comportamiento incoherente con el modelo de
seguridad de confianza parcial de las aplicaciones web.
ApplicationDefinition.
Puede reutilizar o modificar este archivo de proyecto para adaptarlo a sus necesidades, siempre que los
archivos a los que hace referencia se encuentren en la ubicacin desde la que hace referencia a ellos. Como
alternativa, puede hacer que se genere automticamente un archivo de proyecto para una aplicacin
independiente mediante la plantilla de proyecto Aplicacin para Windows (WPF) de Microsoft Visual Studio
2005.
Este archivo de proyecto es para un proyecto de C# y, por tanto, incluye el elemento Import de
Microsoft.CSharp.targets. Microsoft Visual Studio 2005 asigna a los archivos de proyecto de C# una
extensin .csproj. Un proyecto de Microsoft Visual Basic .NET creado en Microsoft Visual Studio 2005 tendra
normalmente la extensin .vbproj e incluira el elemento Import de Microsoft.VisualBasic.targets.
Ejemplo
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<RootNamespace>WPFStandaloneApplication</RootNamespace>
<AssemblyName>WPFStandaloneApplication</AssemblyName>
<WarningLevel>4</WarningLevel>
<OutputType>winexe</OutputType>
<ApplicationVersion>1.0.0.*</ApplicationVersion>
<BootstrapperEnabled>false</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>.\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>false</DebugSymbols>
<Optimize>true</Optimize>
<OutputPath>.\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
ApplicationDefinition.
Puede reutilizar o modificar este archivo de proyecto para adaptarlo a sus necesidades, siempre que los
archivos a los que hace referencia se encuentren en la ubicacin desde la que hace referencia a ellos. Como
alternativa, puede tener un archivo de proyecto para una aplicacin de navegacin independiente generada
automticamente para usted utilizando la plantilla de proyecto Aplicacin para Windows (WPF) de Microsoft
Visual Studio 2005 y reemplazando al Window predeterminado por un Page.
Este archivo de proyecto es para un proyecto de C# y, por tanto, incluye el elemento Import de
Microsoft.CSharp.targets. Microsoft Visual Studio 2005 asigna a los archivos de proyecto de C# una
extensin .csproj. Un proyecto de Microsoft Visual Basic .NET creado en Microsoft Visual Studio 2005 tendra
normalmente la extensin .vbproj e incluira el elemento Import de Microsoft.VisualBasic.targets.
Ejemplo
<Project DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<RootNamespace>WPFStandaloneNavigationApplication</RootNamespace>
<AssemblyName>WPFStandaloneNavigationApplication</AssemblyName>
<WarningLevel>4</WarningLevel>
<OutputType>winexe</OutputType>
<ApplicationVersion>1.0.0.*</ApplicationVersion>
<BootstrapperEnabled>false</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>.\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>false</DebugSymbols>
<Optimize>true</Optimize>
<OutputPath>.\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
HostInBrowser. Se debe establecer en true porque las Aplicaciones del explorador XAML (XBAPs) deben
hospedarse en el explorador.
Install. Se debe establecer en false porque las Aplicaciones del explorador XAML (XBAPs) no se
instalan.
TargetZone. Se debe establecer en "Internet", porque las Aplicaciones del explorador XAML (XBAPs) se
ejecutan en la zona de seguridad de Internet.
ApplicationDefinition.
Puede reutilizar o modificar este archivo de proyecto para adaptarlo a sus necesidades, siempre que los
archivos a los que hace referencia se encuentren en la ubicacin desde la que hace referencia a ellos. Como
alternativa, puede hacer que se genere automticamente un archivo de proyecto para una XBAP mediante la
plantilla de proyecto Aplicacin del explorador XAML (WPF) de Microsoft Visual Studio 2005.
Este archivo de proyecto es para un proyecto de C# y, por tanto, incluye el elemento Import de
Microsoft.CSharp.targets. Microsoft Visual Studio 2005 asigna a los archivos de proyecto de C# una
extensin .csproj. Un proyecto de Microsoft Visual Basic .NET creado en Microsoft Visual Studio 2005 tendra
normalmente la extensin .vbproj e incluira el elemento Import de Microsoft.VisualBasic.targets.
Ejemplo
Puede reutilizar o modificar este archivo de proyecto para adaptarlo a sus necesidades, siempre que los
archivos a los que hace referencia se encuentren en la ubicacin desde la que hace referencia a ellos.
Alternativamente, puede hacer que se genere automticamente un archivo de proyecto para un control
personalizado mediante la plantilla de proyecto Biblioteca de controles personalizados (WPF) en Microsoft Visual
Studio 2005.
Este archivo de proyecto es para un proyecto de C# y, por tanto, incluye el elemento Import de
Microsoft.CSharp.targets. Microsoft Visual Studio 2005 asigna a los archivos de proyecto de C# una
2.7.3.6. Cmo: Configurar IIS 5.0 e IIS 6.0 para Implementar Aplicaciones de
WPF
Puede implementar una aplicacin de Windows Presentation Foundation (WPF) desde la mayora de los
servidores web, siempre que estn configurados con los tipos Extensiones multipropsito de correo Internet
(MIME) adecuados. De manera predeterminada, Microsoft Internet Information Services (IIS) 7.0 se configura
con estos tipos MIME, pero Microsoft Internet Information Services (IIS) 5.0 y Microsoft Internet Information
Services (IIS) 6.0, no.
En este tema se describe cmo configurar Microsoft Internet Information Services (IIS) 5.0 y Microsoft Internet
Information Services (IIS) 6.0 para implementar aplicaciones de WPF.
Nota:
Puede comprobar la cadena UserAgent del Registro para determinar si un sistema tiene .NET Framework
instalado. Para obtener informacin detallada y un script que examina la cadena UserAgent para determinar
si .NET Framework est instalado en un sistema.
Ajustar la configuracin de la expiracin del contenido
Debe ajustar el valor de la expiracin del contenido a 1 minuto. En el siguiente procedimiento se indica cmo
hacerlo con IIS.
1.
Haga clic en el men Inicio, seleccione Herramientas administrativas y, a continuacin, haga clic
en Administrador de Internet Information Services (IIS). Tambin puede iniciar esta aplicacin
desde la lnea de comandos con "%SystemRoot%\system32\inetsrv\iis.msc".
2.
3.
Haga clic con el botn secundario en Sitio web predeterminado y seleccione Propiedades en el
men contextual.
4.
5.
Debe registrar varios tipos MIME y extensiones de archivo para que el explorador del sistema cliente pueda
cargar el controlador correcto. Debe agregar los tipos siguientes:
Extensin
Tipo MIME
.manifest
application/manifest
.xaml
application/xaml+xml
.application
application/x-ms-application
.xbap
application/x-ms-xbap
.deploy
application/octet-stream
.xps
application/vnd.ms-xpsdocument
Nota:
No necesita registrar los tipos MIME ni las extensiones de archivo en los sistemas cliente. Se registran
automticamente al instalar Microsoft .NET Framework.
En el ejemplo de Microsoft Visual Basic Scripting (VBScript) siguiente se agregan automticamente los tipos
MIME necesarios a IIS. Para utilizar el script, copie el cdigo en un archivo .vbs de su servidor. A continuacin,
ejecute el script desde la lnea de comandos o haga doble clic en l desde el Microsoft Windows Explorer.
' This script adds the necessary Windows Presentation Foundation MIME types
' to an IIS Server.
' To use this script, just double-click or execute it from a command line.
' Running this script multiple times results in multiple entries in the IIS MimeMap.
Dim MimeMapObj, MimeMapArray, MimeTypesToAddArray, WshShell, oExec
Const ADS_PROPERTY_UPDATE = 2
' Set the MIME types to be added
MimeTypesToAddArray = Array(".manifest", "application/manifest", ".xaml", _
"application/xaml+xml", ".application", "application/x-ms-application", _
".deploy", "application/octet-stream", ".xbap", "application/x-ms-xbap", _
".xps", "application/vnd.ms-xpsdocument")
' Get the mimemap object
Set MimeMapObj = GetObject("IIS://LocalHost/MimeMap")
' Call AddMimeType for every pair of extension/MIME type
For counter = 0 to UBound(MimeTypesToAddArray) Step 2
AddMimeType MimeTypesToAddArray(counter), MimeTypesToAddArray(counter+1)
Next
' Create a Shell object
Set WshShell = CreateObject("WScript.Shell")
' Stop and Start the IIS Service
cscript DiscoverIISMimeTypes.vbs
C:\WINDOWS\System32\PresentationHost.exe
4. En la seccin Opciones de inicio, escriba lo siguiente en el cuadro de texto Argumentos de la lnea de
comandos:
-debug nombre_de_archivo
El valor del nombre_de_archivo del parmetro -debug es el nombre del archivo .xbap; por ejemplo:
-debug c:\example.xbap
Nota:
sta es la configuracin predeterminada para las soluciones que se crean con la plantilla del proyecto
Aplicacin del explorador XAML (WPF) de Visual Studio 2005.
3.
4.
-debugSecurityZoneURL URL
El valor de URL del parmetro -debugSecurityZoneURL es la URL de la ubicacin que desea indicar
como sitio de origen simulado de la aplicacin.
A modo de ejemplo, supongamos que una Aplicacin del explorador XAML (XBAP) utiliza un servicio web con la
URL siguiente:
http://services.msdn.microsoft.com/ContentServices/ContentService.asmx
La URL del sitio de origen de este servicio web es:
http://services.msdn.microsoft.com
Por consiguiente, el parmetro de lnea de comandos -debugSecurityZoneURL completo con su valor es:
-debugSecurityZoneURL http://services.msdn.microsoft.com
}
//
// Extract the numeric part of the version string.
//
function GetVersion(versionString)
{
var numericString =
versionString.match(/([0-9]+)\.([0-9]+)\.([0-9]+)/i);
return numericString.slice(1);
}
//
// Compare the 2 version strings by converting them to numeric format.
//
function CompareVersions(version1, version2)
{
for (i = 0; i < version1.length; ++i)
{
var number1 = new Number(version1[i]);
var number2 = new Number(version2[i]);
This machine has the correct version of the .NET Framework 3.0: 3.0.04425.00
This machine's userAgent string is: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; InfoPath.1;
.NET CLR 2.0.50727; .NET CLR 3.0.04425.00).
De lo contrario, aparece un mensaje de estado del tipo siguiente:
This machine does not have correct version of the .NET Framework 3.0.
This machine's userAgent string is: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; InfoPath.1;
.NET CLR 2.0.50727).
This machine has the correct version of the .NET Framework 3.5.
This machine's userAgent string is: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727;
.NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.0.590; .NET CLR 3.5.20726; MS-RTC LM 8).
De lo contrario, aparecer el siguiente tipo de mensaje de estado:
This machine does not have the correct version of the .NET Framework 3.5. The required version is v3.5.0.0.
This machine's userAgent string is: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727;
.NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.0.590; MS-RTC LM 8).
Windows Presentation Foundation Plugin for Mozilla Firefox is not installed. Please install or reinstall the .NET
Framework 3.5.
Si el script est hospedado en un explorador diferente de Firefox 2.0+, aparecer el mensaje de estado
siguiente:
2.8. Rendimiento
Para obtener un rendimiento ptimo de la aplicacin, se requiere una reflexin previa sobre el diseo de la
aplicacin y una comprensin de las prcticas recomendadas para el desarrollo de aplicaciones Windows
Presentation Foundation (WPF). Los temas de esta seccin proporcionan informacin adicional sobre cmo
generar aplicaciones WPF de alto rendimiento.
Compatibilidad con texturas mltiples: la compatibilidad con texturas mltiples hace referencia a
la capacidad de aplicar dos o ms texturas distintas durante una operacin de mezcla en un objeto
grfico 3D. El grado de compatibilidad con texturas mltiples viene determinado por el nmero de
unidades de textura mltiple en el hardware grfico.
Nivel de representacin 1 Aceleracin parcial del hardware grfico. El nivel de versin de DirectX es
mayor o igual a la versin 7.0 y menor que la versin 9.0.
La propiedad Tier permite recuperar el nivel de representacin en el tiempo de ejecucin de la aplicacin, lo que
permite a los programadores determinar si el dispositivo puede admitir ciertas caractersticas de aceleracin de
grficos por hardware. La aplicacin puede tomar a continuacin diferentes rutas de cdigo en tiempo de
ejecucin en funcin del nivel de representacin que admita el dispositivo.
Nivel de representacin 0
Un valor de nivel de representacin 0 significa que no hay ninguna aceleracin de hardware grfico disponible
para la aplicacin en el dispositivo. En este nivel, los programadores deben suponer que el software
representar todos los grficos, sin aceleracin de hardware. La funcionalidad de este nivel corresponde a una
versin de DirectX inferior a la 7.0.
Nivel de representacin 1
Un valor de nivel de representacin de 1 significa que en la tarjeta de vdeo est disponible una aceleracin
parcial del hardware grfico. Esto corresponde a una versin de DirectX mayor o igual a 7.0 y menor que 9.0.
Las caractersticas y funciones siguientes son aceleradas por hardware para el nivel de representacin 1:
Caracterstica
Notas
Representacin
de 2D
Rasterizacin 3D
Filtrado
anisotrpico 3D
Asignacin del
mip 3D
Las caractersticas y funciones siguientes no son aceleradas por hardware para el nivel de representacin 1:
Caracterstica
Notas
Contenido impreso
Contenido rasterizado
Todo
el
contenido
representado
usando
el
mtodo
Render
de
utilizando un objeto
RenderTargetBitmap
RenderTargetBitmap.
Ventanas superpuestas
AllowsTransparency = true
Background = Transparent
Degradados radiales
Clculos de iluminacin 3D
Representacin de texto
Suavizado 3D (anti-aliasing)
Notas
Versin de DirectX
RAM de vdeo
La tabla siguiente muestra tarjetas grficas comunes que permiten la representacin de nivel 1:
Manufacturer
Modelo
ATI
Modelos Radeon: 256, 7000, 7500, 8500, 9000, 9100, 9200 y 9250
Intel
NVidia
GeForce
Modelos
Modelos
Modelos
256
GeForce2: GTS, MX, MX100, MX200, MX400, Pro, Ti y Ultra
GeForce3: Ti200 y Ti500
GeForce4: MX420, MX440, MX460, MX4000, Ti4200, Ti4400, Ti4600 y Ti4800
Nivel de representacin 2
Un valor de nivel de representacin 2 significa que la mayora de las caractersticas grficas de WPF deben
utilizar la aceleracin de hardware, siempre y cuando no se hayan agotado los recursos necesarios del sistema.
Esto corresponde a una versin de DirectX mayor o igual a 9,0.
Notas
Caractersticas del
nivel 1
Degradados
radiales
Clculos de
iluminacin 3D
WPF realiza la iluminacin por vrtices, lo que significa que debe calcularse una
intensidad de luz en cada vrtice para cada material que se aplique a una malla. En el
nivel 1, los clculos se realizan mediante software. En el nivel 2, los clculos se
realizan en el hardware.
Representacin de
texto
Suavizado 3D
(anti-aliasing)
Las caractersticas y funciones siguientes no son aceleradas por hardware para el nivel de representacin 2:
Caracterstica
Notas
Contenido impreso
Contenido
representado
RenderTargetBitmap.
Ventanas superpuestas
usando
AllowsTransparency = true
Background = Transparent
el
mtodo
Render
de
Notas
Versin de DirectX
RAM de vdeo
Sombreador de pxeles
Sombreador de vrtices
La tabla siguiente muestra tarjetas grficas comunes que permiten la representacin de nivel 2:
Manufacturer
Modelo
ATI
Intel
NVidia
Otros recursos
Los recursos siguientes pueden ayudarle a analizar las caractersticas de rendimiento de la aplicacin WPF.
Configuracin del Registro en la representacin de grficos
WPF proporciona cuatro valores del Registro para controlar la representacin de WPF:
Valor
Descripcin
Deshabilitar la opcin de
aceleracin de hardware
Utilizar la opcin de
rasterizador de referencia
Cualquier utilidad de configuracin externa que pueda hacer referencia a los valores del Registro de WPF puede
tener acceso a estos valores. Estos valores se pueden crear o modificar tambin mediante el acceso directo a
los valores utilizando el Editor del Registro de Windows.
Herramientas de generacin de perfiles de rendimiento para WPF
WPF proporciona un conjunto de herramientas de creacin de perfiles de rendimiento que permiten analizar el
funcionamiento en tiempo de ejecucin de la aplicacin y determinar los tipos de optimizacin del rendimiento
que se pueden aplicar. La tabla siguiente muestra las cinco herramientas de generacin de perfiles de
rendimiento que se incluyen en la herramienta Windows SDK, WPFPerf:
Herramienta
Descripcin
Event Trace
Perforator
Trace Viewer
Visual Profiler
Se utiliza para generar perfiles de uso de servicios WPF, tales como el diseo y el
control de eventos, mediante elementos del rbol visual.
Working Set
Viewer
El conjunto de herramientas Visual Profiler ofrece una vista grfica y enriquecida de los datos de rendimiento.
En esta captura de pantalla, la seccin CPU Usage de Visual Profiles ofrece un desglose preciso del uso, por
parte de un objeto, de servicios de WPF tales como la representacin y el diseo.
Resultados de la presentacin de Visual Profiler
Compatibilidad con texturas mltiples: la compatibilidad con texturas mltiples hace referencia a
la capacidad de aplicar dos o ms texturas distintas durante una operacin de mezcla en un objeto
grfico 3D. El grado de compatibilidad con texturas mltiples viene determinado por el nmero de
unidades de textura mltiple en el hardware grfico.
Nivel de representacin 1 Aceleracin parcial del hardware grfico. El nivel de versin de DirectX es
mayor o igual a la versin 7.0 y menor que la versin 9.0.
Un objeto UIElement secundario comienza el proceso de diseo con la medicin de sus propiedades
bsicas.
Se evalan las propiedades del objeto FrameworkElement relacionadas con el tamao, tales como
Width, Height y Margin.
Se aplica la lgica concreta de Panel, tal como la propiedad Dock de DockPanel o la propiedad
Orientation de StackPanel.
El contenido se organiza o se coloca una vez medidos todos los objetos secundarios.
La coleccin de objetos secundarios se dibuja en la pantalla.
Se invoca de nuevo el proceso de paso de diseo si se produce cualquiera de las acciones siguientes:
Ascendente
366
454
Descendente
11
96
El objeto GeometryDrawing se utiliza para representar contenido de geometra. La clase Geometry y las clases
concretas que se derivan de ella, tales como CombinedGeometry, EllipseGeometry y PathGeometry,
proporcionan un medio para representar grficos 2D, adems de compatibilidad con las pruebas de
posicionamiento y el recorte. Los objetos de geometra se pueden utilizar para definir la regin de un control,
por ejemplo, o definir la regin de recorte que se aplicar a una imagen. Los objetos de geometra pueden ser
regiones simples, tales como rectngulos y crculos, o bien regiones compuestas creadas a partir de dos o ms
objetos de geometra. Las regiones de geometra ms complejas se pueden crear combinando objetos
derivados de PathSegment, como ArcSegment, BezierSegment y QuadraticBezierSegment.
Aparentemente, la clase Geometry y la clase Shape son bastante similares. Ambas se utilizan para representar
grficos 2D y tienen clases concretas similares que se derivan de ellas, por ejemplo, EllipseGeometry y Ellipse.
Sin embargo, existen diferencias importantes entre estos dos conjuntos de clases. En primer lugar, la clase
Geometry carece de parte de la funcionalidad de la clase Shape, como la capacidad de dibujarse a s misma.
Para dibujar un objeto de geometra, deber utilizarse otra clase, del tipo de DrawingContext, Drawing o Path
(cabe destacar que Path es una forma) para realizar la operacin de dibujo. Las propiedades de representacin,
tales como el relleno, el trazo y el grosor del trazo pertenecen a la clase que dibuja el objeto de geometra,
mientras que un objeto de forma contiene estas propiedades. Podemos pensar en esta diferencia de la siguiente
manera: un objeto de geometra define una regin, un crculo por ejemplo, mientras que un objeto de forma
define una regin, define cmo se rellena y perfila esa regin, y participa en el sistema de diseo.
Puesto que los objetos Shape se derivan de la clase FrameworkElement, utilizarlos puede aumentar
significativamente el consumo de memoria de la aplicacin. Si realmente no necesita las caractersticas de
FrameworkElement para el contenido grfico, es conveniente utilizar los objetos Drawing, ms ligeros.
Objetos StreamGeometry
El objeto StreamGeometry constituye una alternativa ligera a PathGeometry para crear formas geomtricas.
Utilice una StreamGeometry si necesita describir una geometra compleja. StreamGeometry est optimizada
para administrar muchos objetos PathGeometry y registra un rendimiento mejor que cuando se utilizan varios
objetos PathGeometry individuales.
En el ejemplo siguiente se utiliza la sintaxis de atributo para crear una StreamGeometry triangular en XAML.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Path Data="F0 M10,100 L100,100 100,50Z"
StrokeThickness="1" Stroke="Black"/>
</StackPanel>
</Page>
Objetos DrawingVisual
El objeto DrawingVisual es una clase de dibujo ligera que se utiliza para representar formas, imgenes o texto.
Esta clase se considera ligera porque no proporciona administracin del diseo ni control de eventos, lo que
mejora su rendimiento. Por esta razn, los dibujos son idneos para fondos e imgenes prediseadas.
Si su aplicacin le exige que muestre imgenes en miniatura, puede ser conveniente crear una versin
de dimensiones reducidas de la imagen. De manera predeterminada, WPF carga la imagen y la
descodifica a su tamao completo. Si slo desea una versin en miniatura de la imagen, WPF
descodifica innecesariamente la imagen a su tamao completo y, a continuacin, la reduce a la escala
en miniatura. Para evitar este consumo de recursos innecesario, puede solicitar a WPF que
descodifique la imagen a un tamao en miniatura o bien solicitar a WPF que cargue una imagen en
miniatura.
Si es posible, combine las imgenes en una imagen nica, como una tira cinematogrfica creada de
varias imgenes.
BitmapScalingMode
Al animar la escala de un mapa de bits, el algoritmo de remuestreo predeterminado de las imgenes de alta
calidad, a veces, puede consumir tantos recursos del sistema que cause la degradacin de la velocidad de los
fotogramas, lo que provoca el parpadeo de las animaciones. Estableciendo la propiedad BitmapScalingMode del
objeto RenderOptions en LowQuality, puede crear una animacin ms suavizada al escalar un mapa de bits. El
modo LowQuality indica al motor de representacin de WPF que cambie de un algoritmo optimizado para la
calidad a un algoritmo optimizado para la velocidad al procesar las imgenes.
En el siguiente ejemplo se muestra cmo establecer el valor de BitmapScalingMode para un objeto de imagen.
// Set the bitmap scaling mode for the image to render faster.
RenderOptions.SetBitmapScalingMode(MyImage, BitmapScalingMode.LowQuality);
CachingHint
De manera predeterminada, WPF no almacena en memoria cach el contenido representado de los objetos
TileBrush, como DrawingBrush y VisualBrush. En escenarios estticos donde no cambia el contenido ni el uso de
TileBrush en la escena, esto tiene sentido dado que conserva la memoria de vdeo. No tiene tanto sentido
cuando se usa un objeto TileBrush con contenido esttico de forma no esttica; por ejemplo, cuando se asigna
un objeto DrawingBrush o VisualBrush esttico a la superficie de un objeto 3D que gira. El comportamiento
predeterminado de WPF es volver a representar el contenido completo de cada fotograma de DrawingBrush o
VisualBrush, aunque no cambie el contenido.
Si se establece el valor de la propiedad CachingHint del objeto RenderOptions en Cache, podr aumentar el
rendimiento utilizando versiones almacenadas en memoria cach de los objetos de pincel en mosaico.
Los valores de las propiedades CacheInvalidationThresholdMaximum y CacheInvalidationThresholdMinimum son
valores de tamao relativos que determinan cundo se debe regenerar el objeto TileBrush debido a cambios en
la escala. Por ejemplo, si establece el valor de la propiedad CacheInvalidationThresholdMaximum en 2,0, la
extremarse
las
precauciones
al
definir
propiedades
de
dependencia
en
la
aplicacin.
Si
DependencyProperty slo afecta a las opciones de metadatos de tipo de representacin, y no a otras opciones
de metadatos como AffectsMeasure, debe marcarla como a tal invalidando sus metadatos.
Changed
del
objeto
SolidColorBrush a fin de invalidar la propiedad Fill del objeto Rectangle. En este caso, cada vez que
SolidColorBrush tiene que iniciar su evento Changed, es preciso invocar la funcin de devolucin de llamada
para cada Rectangle: la acumulacin de estas invocaciones de la funcin de devolucin de llamada conlleva
importante reduccin del rendimiento. Adems, agregar y quitar controladores en este punto tambin supone
una intensa carga para el rendimiento, puesto que para hacerlo la aplicacin tiene que recorrer la lista
completa. Si en el escenario de aplicacin SolidColorBrush nunca cambia, estar pagando el costo de mantener
innecesariamente los controladores de eventos Changed.
Inmovilizar un objeto Freezable puede mejorar su rendimiento, porque ya no es preciso dedicar recursos a
mantener notificaciones de cambio. En la tabla siguiente se muestra el tamao de un SolidColorBrush simple
Tamao
SolidColorBrush inmovilizado
212 bytes
SolidColorBrush no inmovilizado
972 bytes
}
Los controladores modificados de objetos Freezable no inmovilizados pueden mantener los objetos
activos
El delegado que un objeto pasa al evento Changed de un objeto Freezable es, en realidad, una referencia a ese
objeto. Por consiguiente, los controladores de eventos Changed pueden mantener los objetos activos durante
ms tiempo de lo esperado. Al realizar la limpieza de un objeto que se ha registrado para escuchar a fin de
detectar el evento Changed de un objeto Freezable, es esencial quitar ese delegado antes de liberar el objeto.
WPF tambin enlaza internamente los eventos Changed. Por ejemplo, todas las propiedades de dependencia
que aceptan Freezable como valor escucharn automticamente para detectar los eventos Changed. La
propiedad Fill, que acepta un Brush, muestra este concepto.
Brush myBrush = new SolidColorBrush(Colors.Red);
Rectangle myRectangle = new Rectangle();
myRectangle.Fill = myBrush;
Al asignar myBrush a myRectangle.Fill, un delegado que seala hacia atrs al objeto Rectangle se agregar al
evento Changed del objeto SolidColorBrush. Esto significa que el cdigo siguiente realmente no hace que
myRect sea apto para la recoleccin de elementos no utilizados:
myRectangle = null;
En este caso, myBrush mantiene myRectangle activo y le devolver la llamada cuando provoque su evento
Changed. Observe que al asignar myBrush a la propiedad Fill de un nuevo Rectangle, simplemente se agrega
otro controlador de eventos a myBrush.
La manera recomendada de limpiar estos tipos de objetos es quitar Brush de la propiedad Fill, lo que, a su vez,
quitar el controlador de eventos de Changed.
myRectangle.Fill = null;
myRectangle = null;
Virtualizacin de la interfaz de usuario
WPF tambin proporciona una variacin del elemento StackPanel que "virtualiza" automticamente el contenido
secundario enlazado a datos. En este contexto, el trmino "virtualizar" se refiere a una tcnica por la que se
genera un subconjunto de elementos UIElements a partir de un nmero mayor de elementos de datos en
funcin de los elementos que estn visibles en pantalla. Generar un gran nmero de elementos de interfaz de
usuario cuando slo pueden estar en pantalla algunos de ellos en un momento dado, requiere un uso intensivo,
tanto de la memoria como del procesador. VirtualizingStackPanel (a travs de una funcionalidad proporcionada
por VirtualizingPanel) calcula los elementos visibles y trabaja con ItemContainerGenerator desde un
ItemsControl (como ListBox o ListView) para crear nicamente los UIElements correspondientes a los
elementos visibles.
Para optimizar el rendimiento, los objetos visuales correspondientes a estos elementos se generan o mantienen
activos nicamente si estn visibles en la pantalla. Cuando ya no se encuentran en el rea visible del control,
los objetos visuales se pueden quitar. Esto no debe confundirse con la virtualizacin de datos, donde los objetos
StackPanel
3210
VirtualizingStackPanel
46
la
aplicacin
utiliza
controles
personalizados
define
recursos
en
un
diccionario
de
recursos
(ResourceDictionary) (o nodo de recursos XAML), se recomienda que defina los recursos en el nivel del objeto
Application o Window, o bien que los defina en el tema predeterminado para los controles personalizados.
Definir los recursos en un control ResourceDictionary personalizado afecta negativamente al rendimiento para
cada instancia de ese control. Por ejemplo, si ha realizado operaciones de pincel que deterioran el rendimiento
definidas como parte de la definicin de recurso de un control personalizado y muchas instancias del control
personalizado, el espacio de trabajo de la aplicacin aumentar significativamente.
Para ilustrar este punto, estudie lo siguiente. Supongamos que est programando un juego de cartas mediante
WPF. Para la mayora de los juegos de cartas, necesita 52 cartas con 52 caras diferentes. Decide implementar
un control de carta personalizado y definen 52 pinceles (cada uno de ellos representa una cara de carta) en los
recursos del control de carta personalizado. En la aplicacin principal, crea inicialmente 52 instancias del control
de carta personalizado. Cada instancia del control de carta personalizado genera 52 instancias de objetos
Brush, con lo que tenemos un total de 52 * 52 objetos Brush en la aplicacin. Si saca los pinceles de los
recursos del control personalizado y los coloca en el nivel del objeto Application o Window, o los define en el
tema predeterminado del control personalizado, reducir el espacio de trabajo de la aplicacin, puesto que
ahora compartir los 52 pinceles entre las 52 instancias del control de carta.
Compartir un pincel sin copiar
Si tiene varios elementos que utilizan el mismo objeto Brush, defina el pincel como un recurso y haga
referencia a l, en lugar de definir el pincel insertado en XAML. Este mtodo crear una instancia y la
reutilizar, mientras que al definir los pinceles insertados en XAML, se crea una nueva instancia para cada
elemento.
En el ejemplo de marcado siguiente se ilustra este punto:
<StackPanel.Resources>
<LinearGradientBrush x:Key="myBrush" StartPoint="0,0.5" EndPoint="1,0.5"
Opacity="0.5">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="GoldenRod" Offset="0" />
<GradientStop Color="White" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</StackPanel.Resources>
<!-- Non-shared Brush object. -->
<Label>
Label 1
2.8.2.7. Texto
WPF incluye compatibilidad con la presentacin de contenido de texto mediante controles de interfaz de usuario
(UI) de caractersticas enriquecidas. En general, puede dividir la representacin de texto en tres capas:
1.
2.
3.
Escenarios de impresin.
Nota:
Glyphs y GlyphRun se han diseado para la presentacin de documentos de formato fijo y escenarios de
impresin. Windows Presentation Foundation (WPF) proporciona varios elementos para escenarios
generales de diseo e interfaz de usuario (UI), como Label y TextBlock.
En los ejemplos siguientes se muestra cmo definir las propiedades de un objeto Glyphs en Lenguaje de
marcado de aplicaciones extensible (XAML). El objeto Glyphs representa la salida de GlyphRun en XAML. En los
ejemplos se supone que las fuentes Arial, Courier New y Times New Roman estn instaladas en la carpeta
C:\WINDOWS\Fonts del equipo local.
<!-- The example shows how to use a Glyphs object. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel Background="PowderBlue">
<Glyphs
FontUri
= "C:\WINDOWS\Fonts\TIMES.TTF"
FontRenderingEmSize = "100"
StyleSimulations
= "BoldSimulation"
UnicodeString
= "Hello World!"
Fill
= "Black"
OriginX
= "100"
OriginY
= "200" />
</StackPanel>
</Page>
Utilizar DrawGlyphRun
Si tiene un control personalizado y desea representar glifos, utilice el mtodo DrawGlyphRun.
WPF tambin proporciona servicios del nivel inferior para dar formato personalizado al texto mediante el objeto
FormattedText. La manera ms eficaz de representar texto en Windows Presentation Foundation (WPF) es
generar el contenido de texto en el nivel de glifos mediante Glyphs y GlyphRun. Sin embargo, el costo de esta
eficacia es la prdida de las caractersticas de formato de texto enriquecido fciles de usar integradas en los
controles de Windows Presentation Foundation (WPF), como TextBlock y FlowDocument.
Objeto FormattedText
El objeto FormattedText permite dibujar texto con varias lneas, en el que se puede dar formato a cada carcter
individualmente.
Para crear texto con formato, llame al constructor FormattedText para crear un objeto FormattedText. Una vez
creada la cadena de texto con formato inicial, puede aplicarle varios estilos de formato. Si desea que la
aplicacin implemente su propio diseo, el objeto FormattedText es ms adecuado que usar control, como
TextBlock.
El objeto FormattedText proporciona la funcin de formato de texto de bajo nivel. Puede aplicar varios estilos
de formato a uno o ms caracteres. Por ejemplo, podra llamar a los mtodos SetFontSize y SetForegroundBrus
para cambiar el formato de los cinco primeros caracteres del texto.
En el ejemplo de cdigo siguiente se crea un objeto FormattedText y se representa.
protected override void OnRender(DrawingContext drawingContext)
{
string testString = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed
do eiusmod tempor";
// Create the initial formatted text string.
FormattedText formattedText = new FormattedText(testString,
CultureInfo.GetCultureInfo("en-us"),FlowDirection.LeftToRight,
new Typeface("Verdana"),32,Brushes.Black);
// Set a maximum width and height. If the text overflows these values, an ellipsis
"..." appears.
formattedText.MaxTextWidth = 300;
formattedText.MaxTextHeight = 240;
// Use a larger font size beginning at the first (zero-based) character and
continuing for 5 characters.
// The font size is calculated in terms of points -- not as device-independent
pixels.
formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5);
// Use a Bold font weight beginning at the 6th character and continuing for 11
characters.
formattedText.SetFontWeight(FontWeights.Bold, 6, 11);
Tiempo de creacin
(ms)
Tiempo de representacin
(ms)
146
540
43
453
Label.Content
835
TextBlock.Text
242
Hyperlink
El objeto Hyperlink es un elemento de contenido dinmico insertado que permite hospedar hipervnculos dentro
del contenido dinmico.
Combinar hipervnculos en un solo objeto TextBlock
Puede optimizar el uso de varios elementos Hyperlink agrupndolos dentro del mismo TextBlock. Esto ayuda a
minimizar el nmero de objetos que se crean en la aplicacin. Por ejemplo, puede que desee mostrar varios
hipervnculos, como los siguientes:
MSN Home | My MSN
En el ejemplo de marcado siguiente se muestran varios elementos TextBlock utilizados para mostrar los
hipervnculos:
<!-- Hyperlinks in separate TextBlocks. -->
<TextBlock>
<Hyperlink TextDecorations="None" NavigateUri="http://www.msn.com">MSN
Home</Hyperlink>
</TextBlock>
<TextBlock Text=" | "/>
<TextBlock>
<Hyperlink TextDecorations="None" NavigateUri="http://my.msn.com">My MSN</Hyperlink>
</TextBlock>
En el ejemplo de marcado siguiente se muestra una manera ms eficaz de mostrar los hipervnculos; esta vez,
se utiliza un solo TextBlock:
<!-- Hyperlinks combined in the same TextBlock. -->
<TextBlock>
<Hyperlink TextDecorations="None" NavigateUri="http://www.msn.com">MSN
Home</Hyperlink>
<Run Text=" | " />
<Hyperlink TextDecorations="None" NavigateUri="http://my.msn.com">My MSN</Hyperlink>
</TextBlock>
Mostrar hipervnculos subrayados slo en los eventos MouseEnter
Un objeto TextDecoration es una ornamentacin visual que se puede agregar al texto; sin embargo, la creacin
de instancias puede afectar negativamente al rendimiento. Si realiza un uso excesivo de elementos Hyperlink,
puede ser conveniente mostrar la lnea de subrayado nicamente al desencadenar un evento, como el evento
MouseEnter.
Hipervnculo que aparece al desencadenar MouseEnter
Con subrayado
289
1130
Sin subrayado
299
776
est
deshabilitada.
Puede
habilitar
esta
caracterstica
estableciendo
la
propiedad
IsOptimalParagraphEnabled del objeto en true. Sin embargo, habilitar esta caracterstica afecta al rendimiento
de la aplicacin. Se recomienda no utilizar la caracterstica de prrafo ptimo a menos que lo necesite.
notificaciones
de
cambios
de
propiedad
se
pueden
proporcionar
implementando
la
interfaz
Tiempo de
enlace (ms)
Tiempo de representacin,
incluido el enlace (ms)
115
314
115
305
90
263
Tiempo de enlace
(ms)
950
1200
115
314
solucin
muy
eficaz a
este
problema
es
convertir
la
lista
de
empleados
en
una
coleccin
1656
20
que
sea
posible,
evite
utilizar
el
valor
ScrollBarVisibility.Auto
para
las
propiedades
Debe instalarse el servidor con Windows Vista Ultimate o Windows Vista Enterprise.
El servidor debe tener memoria suficiente para satisfacer los requisitos de memoria del Administrador
de ventanas de escritorio (DWM) (no es imprescindible cumplir otros requisitos de DWM, como los
relativos a las tarjetas de vdeo).
El cliente debe poder ejecutar el Administrador de ventanas de escritorio (DWM) de Windows Vista.
DWM est habilitado cuando el servicio de administracin de sesin del Administrador de ventanas de
escritorio est en ejecucin.
El cliente no debe ejecutar aplicaciones que puedan deshabilitar DWM, tales como rea de encuentro o
Asistencia remota.
El cliente no puede realizar saltos mltiples al servidor que contiene la aplicacin WPF deseada. Saltos
mltiples se refiere a crear una sesin a partir de otra.
Description
Event Trace
Perforator
Trace Viewer
Visual Profiler
Se utiliza para generar perfiles de uso de servicios WPF, tales como el diseo y el
control de eventos, mediante elementos del rbol visual.
Working Set
Viewer
El conjunto de herramientas Visual Profiler ofrece una vista grfica y enriquecida de los datos de rendimiento.
En esta captura de pantalla, la seccin CPU Usage de Visual Profiler ofrece un desglose preciso del uso, por
parte de un objeto, de servicios de WPF tales como la representacin y el diseo.
Resultados de la presentacin de Visual Profiler
Observe que cada uno de los controles Label, TextBox y Button muestra una jerarqua de objetos visuales
independiente en el panel Visual Tree Explorer de XamlPad. Esto se debe a que los controles de WPF tienen una
ControlTemplate que contiene el rbol visual de ese control. Al hacer referencia explcitamente a un control, se
hace referencia implcitamente a su jerarqua visual.
Puede ver los valores de las propiedades de un elemento en Visual Tree Explorer seleccionando el elemento. El
panel Property Tree Explorer, situado debajo del panel Visual Tree Explorer, muestra los valores de las
propiedades actuales del objeto visual seleccionado.
La comunicacin entre las partes administradas y no administradas de WPF se describe ms adelante en este
tema. A continuacin se describe el resto del modelo de programacin administrado.
System.Threading.DispatcherObject
La mayora de los objetos de WPF se derivan de DispatcherObject, que proporciona las estructuras bsicas para
tratar con la simultaneidad y el subprocesamiento. WPF est basado en un sistema de mensajera
implementado por el distribuidor. Funciona de modo similar al conocido suministro de mensajes de Win32; de
hecho, el distribuidor de WPF utiliza los mensajes de User32 para realizar las llamadas entre subprocesos.
Es necesario comprender dos conceptos bsicos al hablar de simultaneidad en WPF: el distribuidor y la afinidad
de subprocesos.
Durante la fase de diseo de WPF, el objetivo era adoptar un nico subproceso de ejecucin, pero perteneciente
a un modelo con afinidad y sin subprocesos. La afinidad de subprocesos se produce cuando un componente
utiliza la identidad del subproceso que se est ejecutando para almacenar algn tipo de estado. La forma ms
comn de esta afinidad es utilizar el almacenamiento local de subprocesos (TLS) para almacenar el estado. La
afinidad de subprocesos requiere que cada subproceso lgico de ejecucin sea propiedad de un nico
subproceso fsico en el sistema operativo, lo que puede consumir mucha memoria. Finalmente, el modelo de
subprocesamiento de WPF se mantuvo sincronizado con el modelo de subprocesamiento de User32 existente,
que consiste en la ejecucin de un solo subproceso con afinidad de subprocesos. La principal razn para esto
fue la interoperabilidad; los sistemas como OLE 2.0, el Portapapeles e Internet Explorer requieren la ejecucin
de afinidad con subproceso nico (STA).
Dado que disponemos de objetos con subprocesamiento STA, necesitamos un medio de comunicacin entre
subprocesos y estar seguros de que nos encontramos en el subproceso correcto. A continuacin se describe la
funcin del distribuidor. El distribuidor es un sistema de envo de mensajes bsico que dispone de varias colas
con prioridad. Por ejemplo, son mensajes las notificaciones de entrada sin formato (el mouse se ha movido),
las funciones de marco de trabajo (diseo) o los comandos de usuario (ejecutar este mtodo). Al realizar una
derivacin de DispatcherObject, se crea un objeto de CLR que tiene el comportamiento de STA y al que se le
proporcionar un puntero a un distribuidor en el momento de la creacin.
System.Windows.DependencyObject
Una de las principales filosofas arquitectnicas utilizadas al crear WPF fue la preferencia por las propiedades en
lugar de los mtodos o los eventos. Las propiedades son declarativas y le permiten especificar ms fcilmente
la intencin en lugar de la accin. Esto tambin permiti el uso de un sistema basado en modelos, o en datos,
para mostrar el contenido de la interfaz de usuario. Esta filosofa tena como objetivo crear ms propiedades
con las que poder enlazar, y as tener un mejor control del comportamiento de una aplicacin.
Para conseguir que ms partes del sistema estuviesen controladas por propiedades, era necesario un sistema
de propiedades ms completo que el proporcionado por CLR. Un ejemplo sencillo de esto son las notificaciones
de cambios. Para poder habilitar los enlaces bidireccionales, ser necesario que ambos lados del enlace admitan
la notificacin de cambios. Para poder tener el comportamiento vinculado a los valores de propiedad, deber
(Ctrl+N
asignado
"Nuevo").
En
el
distribuidor
de
la
aplicacin
se
llamara
TranslateAccelerator, que examinara los mensajes de entrada en User32 y determinara si alguno de ellos
coincide con un acelerador registrado. En WPF esto no funcionara, ya que el sistema es totalmente "ajustable",
es decir, que cualquier elemento puede controlar y utilizar cualquier acelerador de teclado. Tener este modelo
de dos fases para la entrada permite a los componentes implementar su propio "TranslateAccelerator".
Para ir incluso un poco ms lejos, UIElement introduce tambin el concepto de CommandBindings. El sistema
de comandos de WPF permite a los programadores definir la funcionalidad en funcin de un punto final de
comando, algo que implementa ICommand. Los enlaces de comandos permiten a un elemento definir una
asignacin entre un movimiento de entrada (Ctrl+N) y un comando (Nuevo). Tanto los movimientos de entrada
como las definiciones de comandos son extensibles, y pueden conectarse en el momento de su uso. Esto hace
que resulte trivial, por ejemplo, permitir que un usuario final personalice los enlaces de teclado que desea
utilizar dentro de una aplicacin.
Hasta ahora, este tema se ha centrado en las caractersticas "bsicas" de WPF, es decir, las caractersticas
implementadas en el ensamblado PresentationCore. Al concebir WPF, el resultado deseado era una separacin
limpia entre las partes fundamentales (como el contrato para el diseo con Measure y Arrange) y las partes
del marco de trabajo (como la implementacin de un diseo concreto como Grid). El objetivo era proporcionar
un punto de extensibilidad en la zona inferior de la pila que permitira a los programadores externos crear sus
propios marcos de trabajo en caso necesario.
System.Windows.FrameworkElement
FrameworkElement se puede examinar de dos maneras diferentes. Introduce un conjunto de directivas y
personalizaciones en los subsistemas incluidos en las capas inferiores de WPF. Tambin introduce un conjunto
de nuevos subsistemas.
directiva
primaria
introducida
por
FrameworkElement
trata
sobre
el
diseo
de
la
aplicacin.
FrameworkElement se basa en el contrato del diseo bsico introducido por UIElement y agrega el concepto de
una "ranura" de diseo que facilita a los autores del diseo la disponibilidad de un conjunto coherente de
elementos de semntica del diseo orientados a propiedades. Propiedades como HorizontalAlignment,
VerticalAlignment, MinWidth y Margin (por nombrar algunas) proporcionan a todos los componentes derivados
de FrameworkElement un comportamiento coherente dentro de los contenedores de diseo.
FrameworkElement tambin facilita la exposicin de la API a muchas caractersticas situadas en las capas
bsicas de WPF. Por ejemplo, FrameworkElement proporciona acceso directo a la animacin a travs del
mtodo BeginStoryboard. Un objeto Storyboard proporciona una manera de crear scripts para varias
animaciones con un conjunto de propiedades.
Las dos caractersticas ms importantes introducidas por FrameworkElement son el enlace de datos y los
estilos.
El subsistema de enlace de datos de WPF debera resultarle relativamente familiar a cualquiera que haya
utilizado formularios Windows Forms o ASP.NET para crear la interfaz de usuario (UI) de una aplicacin. En
cada uno de estos sistemas, hay una manera sencilla de expresar que se desea enlazar una o varias
propiedades de un elemento determinado a un fragmento de datos. WPF ofrece compatibilidad total para el
enlace de propiedades, la transformacin y el enlace de listas.
Una de las caractersticas ms interesantes del enlace de datos en WPF es la introduccin de plantillas de datos.
Las plantillas de datos le permiten especificar mediante declaracin cmo se debera visualizar un fragmento de
datos. En lugar de crear una interfaz de usuario personalizada que se puede enlazar a los datos, puede
solucionar el problema permitiendo que los datos determinen la presentacin que se va a crear.
La aplicacin de estilos es realmente una forma ligera de enlace de datos. El uso de estilos le permite enlazar
un conjunto de propiedades de una definicin compartida a una o varias instancias de un elemento. Los estilos
se aplican a un elemento, bien mediante una referencia explcita (estableciendo la propiedad Style) o bien de
forma implcita asociando un estilo al tipo CLR del elemento.
System.Windows.Controls.Control
La caracterstica ms significativa del control es la definicin de plantillas. Si piensa en el sistema de
composicin de WPF como en un sistema de representacin de modo retenido, la definicin de plantillas permite
a un control describir su representacin de una manera parametrizada y declarativa. En realidad,
ControlTemplate es simplemente un script que permite crear un conjunto de elementos secundarios, con
enlaces a las propiedades proporcionadas por el control.
Control proporciona un conjunto de propiedades estndar, como Foreground, Background y Padding, por citar
algunas, que los autores de las plantillas pueden utilizar para personalizar la presentacin de un control. La
implementacin de un control proporciona un modelo de datos y un modelo de interaccin. El modelo de
interaccin define un conjunto de comandos (como Cerrar para una ventana) y enlaces a movimientos de
entrada (como hacer clic en la X roja situada en la esquina superior de la ventana). El modelo de datos
proporciona un conjunto de propiedades para personalizar el modelo de interaccin o la presentacin
(determinado por la plantilla).
Esta diferencia entre el modelo de datos (propiedades), el modelo de interaccin (comandos y eventos) y el
modelo de presentacin (plantillas) permite una total personalizacin de la apariencia y el comportamiento de
un control.
Un aspecto comn del modelo de datos de los controles es el modelo de contenido. Si examina un control como
Button, ver que tiene una propiedad denominada "Content" de tipo Object. En formularios Windows Forms y
ASP.NET, esta propiedad sera normalmente una cadena; sin embargo, esto limita el tipo de contenido que
3.2. XAML
Lenguaje de marcado de aplicaciones extensible (XAML) es un lenguaje de marcado para la programacin de
aplicaciones declarativa. Windows Presentation Foundation (WPF) implementa un cargador Lenguaje de
marcado de aplicaciones extensible (XAML) y proporciona compatibilidad el lenguaje Lenguaje de marcado de
aplicaciones extensible (XAML) para los tipos de Windows Presentation Foundation (WPF), de tal forma que se
puede crear la mayor parte de la interfaz de usuario de la aplicacin en marcado Lenguaje de marcado de
aplicaciones extensible (XAML). Adems, el SDK incluye una herramienta de edicin Lenguaje de marcado de
aplicaciones extensible (XAML) denominada XAMLPad. Puede utilizar esta herramienta para realizar pruebas con
Lenguaje de marcado de aplicaciones extensible (XAML) en tiempo real.
Elemento
de
objeto
UIElementCollection
omitido:
La
propiedad
Children
toma
el
tipo
UIElementCollection, que implementa IList. Por consiguiente, se puede omitir la etiqueta de elemento
de objeto UIElementCollection, basndose en las reglas de XAML definidas para las colecciones. En
este caso, no se pueden crear instancias de UIElementCollection como elementos de objeto. Ni siquiera
se tiene la opcin de declarar explcitamente ese objeto de coleccin. Esto se debe a que
UIElementCollection no expone un constructor predeterminado. Otros tipos de coleccin de WPF
de
cualquier
otro
elemento
de
propiedad
en
ese
elemento
de
objeto.
Esto
es
cierto
independientemente de si el valor de una propiedad de contenido XAML se especifica como una cadena o como
uno o varios objetos. Por ejemplo, el marcado siguiente no se puede compilar:
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button
</Button>
Esto no es vlido bsicamente porque si esta sintaxis fuera explcita utilizando la sintaxis de elementos de
propiedad para la propiedad de contenido, sta se establecera dos veces:
<Button>
<Button.Content>I am a </Button.Content>
<Button.Background>Blue</Button.Background>
<Button.Content> blue button</Button.Content>
</Button>
Un ejemplo similar que tampoco es vlido se da cuando la propiedad de contenido es una coleccin y los
elementos secundarios estn intercalados con los elementos de propiedad:
<StackPanel>
<Button>This example</Button>
<StackPanel.Resources>
<SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
</StackPanel.Resources>
<Button>... is illegal XAML</Button>
</StackPanel>
Modelos de contenido
Una clase podra admitir su uso como un elemento XAML en lo referente a la sintaxis, pero dicho elemento slo
funcionar correctamente en una aplicacin o pgina si se coloca en una posicin esperada de un modelo de
contenido o rbol de elementos general. Por ejemplo, un elemento MenuItem se debera colocar normalmente
slo como un elemento secundario de una clase derivada de MenuBase, como Menu. Los modelos de contenido
adicional,
que
asigna
el
espacio
de
nombres
del
lenguaje
XAML
x:Key: establece una clave nica para cada recurso de un elemento ResourceDictionary. x:Key
representar probablemente el 90% de los usos de x: que ver en el marcado de su aplicacin.
x:Class: especifica el espacio de nombres de CLR y el nombre de clase para la clase que proporciona
cdigo subyacente para una pgina XAML. Debe disponer de esta clase para admitir el cdigo
subyacente; por esto casi siempre ver x: asignado, aun cuando no haya ningn recurso.
x:Name: especifica un nombre de objeto en tiempo de ejecucin para la instancia que existe en el
cdigo en tiempo de ejecucin una vez procesado un elemento de objeto. Utilice x:Name para aquellos
casos de asignacin de nombres a elementos en los que no se admite la propiedad de nivel de marco
de trabajo de WPF Name equivalente. Esto sucede en ciertos escenarios de animacin.
x:Static: habilita una referencia de valor que obtiene un valor esttico que de lo contrario no sera una
propiedad XAML que se pudiese establecer.
x:Type: construye una referencia Type basada en un nombre de tipo. Esto se utiliza para especificar
atributos que toman valores Type, como Style.TargetType, aunque en muchos casos la propiedad
dispone de una conversin de cadena a Type nativa y el uso de x:Type es opcional.
Hay construcciones de programacin adicionales en la estructura prefijo x: o xmlns de XAML que no son tan
habituales.
Eventos y el cdigo XAML subyacente
La mayora de las aplicaciones de WPF constan de marcado y cdigo subyacente. Dentro de un proyecto, el
cdigo XAML se escribe como un archivo .xaml y se utiliza un lenguaje de CLR, como Microsoft Visual Basic
.NET o C#, para escribir un archivo de cdigo subyacente. Cuando se compila un archivo XAML, la ubicacin del
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyNamespace.MyPageCode"
>
Debajo de XAML y sus esquemas existe una coleccin de clases que corresponden a los objetos de CLR, as
como elementos de marcado que se van a utilizar en XAML. Sin embargo, no todas las clases se pueden asignar
a elementos. Las clases abstractas, como ButtonBase, y ciertas clases base no abstractas se utilizan para la
herencia en el modelo de objetos CLR y no admiten las etiquetas de marcado XAML correspondientes. Las
clases base, incluso las abstractas, son importantes para el desarrollo en XAML porque cada uno de los
El elemento y la etiqueta deben cerrarse mediante una barra diagonal (/), seguida inmediatamente por
un corchete angular derecho (>).
La etiqueta de apertura debe completarse con un corchete angular derecho (>). Dicha etiqueta puede
ir seguida de otros elementos de objeto, de elementos de propiedad o de texto interno. El tipo exacto
de contenido que se puede incluir aqu viene determinado normalmente por el modelo de objetos del
elemento; vea la seccin Sintaxis de contenido en este mismo tema. Tambin debe existir la etiqueta
de cierre equivalente para el elemento de objeto, anidada y equilibrada correctamente con otras
parejas de etiquetas de apertura y cierre.
Por ejemplo, el ejemplo siguiente es una sintaxis de elementos de objeto que crea una nueva instancia de la
clase Button y tambin especifica un atributo Name y un valor para ese atributo:
<Button Name="CheckoutButton"/>
El ejemplo siguiente es una sintaxis de elementos de objeto que tambin incluye la sintaxis de propiedad de
contenido de Lenguaje de marcado de aplicaciones extensible (XAML). El texto interno incluido dentro se
utilizar para establecer la propiedad de contenido TextBox de Lenguaje de marcado de aplicaciones extensible
(XAML), Text.
<TextBox>This is a Text Box</TextBox>
Sintaxis de atributo
La sintaxis de atributo es la sintaxis de marcado de XAML que establece un valor para una propiedad o
denomina un controlador de eventos para un evento declarando un atributo en un elemento. El elemento
siempre se declara mediante la sintaxis de elementos de objeto. El nombre del atributo debe coincidir con el
nombre de miembro de CLR de una propiedad o un evento. El nombre del atributo va seguido de un operador
de asignacin (=). El valor de atributo debe ser una cadena encerrada entre comillas (").
Para que una propiedad se pueda establecer mediante la sintaxis de atributo, dicha propiedad debe ser pblica,
de lectura y escritura, y tener un tipo de valor de propiedad del que se puedan crear instancias o al que pueda
hacer referencia un procesador de XAML. Para los eventos, el evento debe ser pblico y tener un delegado
pblico. La propiedad o el evento debe ser un miembro de la clase o estructura de la que el elemento de objeto
contenedor crea una instancia.
El valor de atributo se rellena con uno de los valores siguientes, en el orden de procesamiento indicado a
continuacin:
1.
2.
Si no hay TypeConverter, se intenta una conversin directa al tipo de propiedad. Este nivel final es una
conversin directa entre tipos primitivos o una comprobacin de nombres en una enumeracin (que
devuelve los valores correspondientes).
Por ejemplo, utilizando el mismo marcado mostrado previamente, el ejemplo siguiente es la sintaxis de atributo
utilizada para asignar un valor de cadena a la propiedad Name:
<Button Name="CheckoutButton"/>
La propiedad Name es un miembro de la tabla de miembros para la clase Button. Button es una clase derivada
de la clase FrameworkElement que define Name.
Procesamiento de los valores de atributo
El valor de cadena incluido entre las comillas de apertura y cierre es procesado por un procesador de XAML. En
el caso de las propiedades, el comportamiento de procesamiento predeterminado est definido por el tipo de
propiedad de CLR subyacente. Si la propiedad es un tipo primitivo, el valor de atributo se asigna basndose en
la conversin implcita de la cadena al tipo primitivo pertinente. Si la propiedad es una enumeracin, la cadena
se trata como un nombre definido por dicha enumeracin y se devuelve el valor correspondiente de esta. Si la
propiedad no es un tipo primitivo ni una enumeracin, el valor de atributo se deber controlar mediante un
convertidor de tipos declarado en la misma propiedad o en el tipo de destino. El convertidor de tipos debe
proporcionar una conversin que acepte una cadena y debe producir una instancia del tipo de propiedad de CLR
subyacente. El paso de la conversin tambin se podra aplazar mediante una extensin de marcado.
Valores de atributo de enumeracin
Los valores de enumeracin en XAML son procesados intrnsecamente por los mtodos nativos de la estructura
Enum.
Para los valores de enumeracin sin marcadores, el comportamiento nativo consiste en procesar la cadena de
un valor de atributo y resolverlo como uno de los valores de enumeracin. La enumeracin no se especifica en
el formato Enumeracin.Valor, tal y como se hace en el cdigo. En su lugar, slo se especifica Valor, y
Enumeracin se deduce a partir del tipo de la propiedad que se est estableciendo. Si se especifica un atributo
en la forma Enumeracin.Valor, no se resolver correctamente.
Para las enumeraciones basadas en marcadores, el comportamiento est basado en el mtodo Enum.Parse. Se
pueden especificar varios valores para una enumeracin basada en marcadores separando cada valor con una
coma. Sin embargo, no es posible combinar valores de enumeracin que no estn basados en marcadores. Por
ejemplo, no se puede utilizar la sintaxis de comas para intentar crear un valor Trigger que acte en varias
condiciones de una enumeracin sin marcadores:
<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
<Setter ... />
</Trigger>
...
Las enumeraciones basadas en marcadores que admiten atributos que se pueden establecer en XAML no son
frecuentes en WPF. Sin embargo, una de estas enumeraciones es StyleSimulations. Por ejemplo, podra utilizar
la sintaxis de atributo basada en marcadores y separada por comas para modificar el ejemplo incluido en la
seccin Comentarios para la clase Glyphs; StyleSimulations = "BoldSimulation" podra convertirse en
StyleSimulations = "BoldSimulation,ItalicSimulation". KeyBinding.Modifiers es otra propiedad en la que se
pueden especificar varios valores de enumeracin. Sin embargo, esta propiedad es un caso especial, ya que la
enumeracin ModifierKeys admite su propio convertidor de tipos. El convertidor de tipos para los modificadores
utiliza un signo ms (+) como delimitador en lugar de una coma (,) con objeto de que se pueda utilizar en el
marcado la sintaxis ms tradicional para representar las combinaciones de teclas, como "Ctrl+Alt".
Referencias a nombres de miembros de evento y de propiedad
Al especificar un atributo, se puede hacer referencia a cualquier propiedad o evento que exista dentro de la
tabla de miembros del tipo CLR del que se ha creado una instancia para el elemento de objeto contenedor.
Implementa IList.
Implementa IDictionary.
Deriva de Array.
Si el tipo de una propiedad es una coleccin, no es necesario especificar en el marcado el tipo de coleccin que
se deduce. En su lugar, los elementos que van a convertirse en elementos de la coleccin se especifican como
uno o ms elementos secundarios del elemento de propiedad del tipo de coleccin. Cada uno de estos
elementos se evala como un objeto durante la carga y se agrega a la coleccin llamando al mtodo Add de la
coleccin implcita. Por ejemplo, la propiedad Triggers de Style toma el tipo de coleccin especializado
TriggerCollection. Pero no es necesario crear instancias de un objeto TriggerCollection en el marcado. En su
lugar, especifique uno o varios elementos Trigger como elementos dentro del elemento de propiedad
Style.Triggers, donde Trigger (o una clase derivada) es el tipo que se espera como tipo de elemento para el
objeto TriggerCollection con establecimiento inflexible de tipos e implcito.
<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="Button.IsMouseOver" Value="true">
<Setter Property = "Background" Value="Red"/>
</Trigger>
<Trigger Property="Button.IsPressed" Value="true">
<Setter Property = "Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
Una propiedad puede ser tanto un tipo de coleccin como la propiedad de contenido XAML para dicho tipo y los
tipos derivados.
Un elemento de coleccin implcito crea un miembro en el rbol lgico, aunque no aparece en el marcado como
un elemento. Normalmente, el constructor del tipo propietario realiza la creacin de instancias para la coleccin
que es una de sus propiedades, lo que permite agregar la coleccin al rbol.
Nota:
La lista genrica y las interfaces de diccionario (IList<(Of <(T>)>) y IDictionary<(Of <(TKey, TValue>)>))
no las admite el procesador WPFXAML para la deteccin de colecciones. Sin embargo, puede utilizar
List<(Of <(T>)>) como una clase base, ya que implementa directamente IList, o Dictionary<(Of <(TKey,
TValue>)>), ya que esta implementa directamente IDictionary.
Sintaxis de contenido XAML
La sintaxis de contenido XAML es una sintaxis que slo est habilitada en las clases que especifican
ContentPropertyAttribute como parte de su declaracin de clase. El objeto ContentPropertyAttribute requiere un
parmetro que especifique la propiedad por nombre definida para ser la propiedad de contenido de ese tipo de
elemento (incluyendo las clases derivadas). La propiedad as designada es la propiedad de contenido XAML de
un elemento. Cuando lo procesa un procesador de XAML, los elementos secundarios o el texto interno que se
encuentran entre las etiquetas de apertura y cierre del elemento se asignarn como el valor de esa propiedad
de contenido XAML. Las etiquetas de elemento de propiedad en un elemento no se asignan de esta manera; se
procesan primero y no se consideran como "contenido".
Tambin puede utilizar la sintaxis de elementos de propiedad para las propiedades asociadas. Sin
embargo, en la sintaxis de elementos de propiedad tpica, el nombreDeTipo especificado es el
elemento de objeto que contiene el elemento de propiedad. Si est haciendo referencia a una
propiedad asociada, el nombreDeTipo es la clase que define la propiedad asociada, no el elemento de
objeto contenedor.
Eventos asociados
Los eventos asociados son otro concepto de programacin introducido en XAML segn el cual, un tipo puede
definir los eventos, pero los controladores pueden estar asociados a cualquier objeto. A menudo, el tipo que
define un evento asociado es un tipo esttico que define un servicio, y algunas veces estos eventos asociados
estn expuestos por un alias de evento enrutado en los tipos que exponen el servicio. Los controladores para
los eventos asociados se especifican mediante la sintaxis de atributo. Al igual que sucede con los eventos
asociados, la sintaxis de atributo se expande para los eventos asociados con objeto de permitir el uso de
nombreDeTipo.nombreDeEvento, donde nombreDeTipo es la clase que proporciona descriptores de acceso de
controlador de eventos Add y Remove para la infraestructura de evento asociada, y nombreDeEvento es el
nombre del evento.
Espacios de nombres XML.
En ninguno de los ejemplos de sintaxis anteriores se especific un espacio de nombres distinto del
predeterminado. En las aplicaciones de WPF tpicas se especifica el espacio de nombres WPF como espacio de
nombres predeterminado. Puede especificar espacios de nombres distintos del predeterminado y seguir
utilizando prcticamente los mismos tipos de sintaxis, pero siempre que se mencione el nombre de una clase a
la que no se pueda tener acceso dentro del espacio de nombres predeterminado, dicho nombre debe ir
precedido por el prefijo del espacio de nombres de XML que se utiliz para asignar el espacio de nombres de
CLR correspondiente. Por ejemplo, <custom:MyElement/> es la sintaxis de elementos de objeto para crear una
instancia de la clase MyElement, donde el espacio de nombres de CLR que contiene dicha clase (y posiblemente
el ensamblado externo que contiene ese espacio de nombres) se asign previamente al prefijo custom.
Extensiones de marcado
XAML define una entidad de programacin de extensin de marcado que ofrece una va alternativa al control
habitual de atributos o elementos de objetos del procesador de XAML, y cede el procesamiento a una clase de
respaldo. La implementacin de WPF de un procesador de XAML utiliza la clase abstracta MarkupExtension
como base para todas las extensiones de marcado admitidas por WPF. El carcter que identifica una extensin
La clase parcial debe derivarse del tipo de clase utilizado como elemento raz. Puede dejar en blanco la
derivacin en la definicin de clase parcial del cdigo subyacente, pero en este caso en el resultado
compilado se supondr que la raz de la pgina es la clase base de la clase parcial aunque no se
especifique (porque la parte correspondiente al marcado de la clase parcial s especifica la raz de la
pgina como base).
Los controladores de eventos que se escriban deben ser mtodos de instancia definidos por la clase
parcial dentro del espacio de nombres identificado por x:Class. No se puede certificar el nombre de un
controlador de eventos para indicar a un procesador XAML que lo busque en otro mbito de clase.
Tampoco se pueden utilizar mtodos estticos como controladores de eventos.
En particular para el lenguaje Microsoft Visual Basic .NET, puede utilizar la palabra clave Handles
especfica del lenguaje para asociar los controladores a instancias y eventos en la declaracin del
controlador, en lugar de asociar los controladores a los atributos en XAML. Sin embargo, esta tcnica
tiene algunas limitaciones porque Handles no puede admitir todas las caractersticas especficas del
sistema de eventos de WPF, como algunos escenarios de eventos enrutados o asociados.
x:Code
x:Code es un elemento de directiva definido en XAML. Un elemento de directiva x:Code puede contener cdigo
de programacin insertado. El cdigo insertado que se define puede interactuar con XAML en la misma pgina.
En el siguiente ejemplo se ilustra el cdigo insertado C#. Observe que el cdigo est dentro del elemento
x:Code y que el cdigo debe estar entre <CDATA[...]]>, una secuencia de escape para el contenido en XML, de
manera que un procesador XAML (que interprete el esquema de XAML o el esquema de WPF) no intente
interpretar literalmente el contenido como XML.
La ventaja de crear una biblioteca de clases es que cualquiera de esas clases personalizadas puede
compartirse entre muchas posibles aplicaciones diferentes. Una biblioteca independiente tambin
facilita las tareas de control de versin de las aplicaciones y simplifica la creacin de una clase que se
desee utilizar como elemento raz en una pgina XAML.
La ventaja de definir las clases personalizadas en la aplicacin es que esta tcnica es relativamente
ligera, y minimiza los problemas de implementacin y pruebas que se encuentran al introducir
ensamblados independientes adems de la aplicacin ejecutable principal. Sin embargo, una
desventaja notable es que no se puede utilizar clases definidas en el mismo ensamblado como
elemento raz de una pgina XAML.
Ya estn definidas en el mismo ensamblado o en uno diferente, las clases personalizadas deben
asignarse entre el espacio de nombres CLR y el espacio de nombres XML para utilizarse en XAML como
elementos.
La clase personalizada debe ser pblica y admitir un constructor pblico predeterminado (sin
parmetros). (Las
estructuras
de
cdigo
este
tipo
de
constructor.)
La clase personalizada no debe ser una clase anidada (las clases anidadas y el "punto" en su sintaxis
interfieren con otras caractersticas de WPF tales como las propiedades asociadas).
Adems de permitir la sintaxis de elemento de objeto, tambin debe habilitar la sintaxis de elemento de
propiedad para cualquier otra propiedad pblica que admita el objeto como su tipo de valor. Esto se debe a que
ahora es posible crear instancias de un objeto como un elemento de objeto y a que el objeto puede rellenar el
valor de elemento de propiedad de tales propiedades.
Requisitos para las propiedades de una clase personalizada como atributos XAML
Las propiedades deben hacer referencia a un tipo por valor (tal como un tipo primitivo) o utilizar una clase para
tipo que tenga un constructor predeterminado o un convertidor de tipos dedicado en el nivel de clase.
Como alternativa, la propiedad puede hacer referencia a un tipo de clase abstracto o a una interfaz. Para las
clases abstractas o las interfaces, la expectativa en tiempo de ejecucin es que el valor de la propiedad deba
rellenarse con instancias de clase prcticas que implementen la interfaz, o con instancias de clase que deriven
de la clase abstracta.
Es posible declarar propiedades en una clase abstracta, pero solamente se pueden establecer en clases
prcticas que deriven de la clase abstracta, porque la creacin del elemento de objeto para la clase requiere un
constructor predeterminado vlido y una clase que permita crear instancias.
Sintaxis de atributo con convertidor de tipos
Si se proporciona un convertidor de tipos dedicado, con atributos, en el nivel de clase, la conversin de tipos
aplicada habilita la sintaxis de atributo para cualquier propiedad que necesita crear instancias de ese tipo. Un
convertidor de tipos no permite el uso de elemento de objeto del tipo; solamente la presencia de un constructor
predeterminado para ese tipo habilita el uso de elemento de objeto. Por consiguiente, las propiedades
habilitadas con convertidor de tipos, en general, no son utilizables en sintaxis de propiedad, a menos que el
propio tipo admita tambin la sintaxis de elemento de objeto. La excepcin consiste en que se puede especificar
una sintaxis de elemento de propiedad, pero el elemento de propiedad debe contener una cadena. Ese uso es
esencialmente el equivalente a un uso de sintaxis de atributo, realmente; este tipo de uso no es comn a
menos que se necesite una administracin ms slida del espacio en blanco en el valor del atributo. Por
ejemplo, lo siguiente es un uso de elemento de propiedad que toma una cadena y el uso de atributo
equivalente:
<Button>Hallo!
<Button.Language>
de-DE
</Button.Language>
</Button>
<Button Language="de-DE">Hallo!</Button>
Ejemplos de propiedades donde se permite la sintaxis de atributo, pero se rechaza la sintaxis de elemento de
propiedad que contiene un elemento de objeto a travs de XAML, son varias propiedades que toman el tipo
Cursor. La clase Cursor tiene un objeto CursorConverter convertidor de tipos dedicado, pero no expone un
constructor predeterminado, por lo que la propiedad Cursor solamente se puede establecer mediante sintaxis
de atributo aunque el tipo Cursor real sea un tipo de referencia.
Convertidores de tipo por propiedad
La propia propiedad puede declarar tambin un convertidor de tipos en el nivel de propiedad. Esto habilita un
"minilenguaje" que crea instancias de objetos del tipo de la propiedad en el propio cdigo, procesando valores
Implementa IList.
Implementa IDictionary o el equivalente genrico (IDictionary<(Of <(TKey, TValue>)>)).
Deriva de Array.
Implementa IAddChild (una interfaz definida por WPF).
Cada uno de estos tipos tiene un mtodo Add, que es utilizado por el procesador de impresin XAML para
agregar elementos a la coleccin subyacente.
Nota:
Las interfaces genricas de lista y de diccionario (IList<(Of <(T>)>) y IDictionary<(Of <(TKey,
TValue>)>)) no se admiten para la deteccin de colecciones por el procesador WPFXAML. Sin embargo,
puede utilizar List<(Of <(T>)>) como una clase base, ya que implementa directamente IList o
Dictionary<(Of <(TKey, TValue>)>), ya que sta implementa directamente IDictionary.
Al declarar una propiedad que toma una coleccin, tenga cuidado con el modo en el que se inicializa ese valor
de propiedad en las nuevas instancias del tipo. Si no est implementando la propiedad como una propiedad de
dependencia, es aconsejable hacer que la propiedad utilice un campo de respaldo que llame al constructor del
tipo de coleccin. Si la propiedad es una propiedad de dependencia, quiz necesite inicializar la propiedad de
coleccin como parte del constructor de tipo predeterminado. Esto se debe a que una propiedad de
dependencia toma su valor predeterminado de los metadatos y, habitualmente, no se desea que el valor inicial
de una propiedad de coleccin sea una coleccin esttica y compartida (debe haber una instancia de coleccin
por cada instancia del tipo contenedor).
Puede implementar un tipo de coleccin personalizado para la propiedad de coleccin. Debido al tratamiento de
propiedad de coleccin implcito, no es necesario que el tipo de coleccin personalizado proporcione un
constructor predeterminado utilizar implcitamente el tipo en XAML. Sin embargo, puede proporcionar un
constructor predeterminado para el tipo de coleccin. Puede que valga la pena hacerlo as porque, a menos que
proporcione un constructor predeterminado, no podr declarar explcitamente la coleccin como un elemento de
objeto. Es posible que algunos autores de marcado prefieran considerar la coleccin explcita como una cuestin
de estilo de marcado. Adems, un constructor predeterminado puede simplificar los requisitos de inicializacin
al crear nuevos objetos que utilicen el tipo de coleccin como un valor de propiedad.
Declarar propiedades de contenido XAML
El lenguaje XAML define el concepto de una propiedad de contenido XAML. Cada clase utilizable en sintaxis de
objeto puede tener exactamente una propiedad de contenido XAML. Para declarar una propiedad para que sea
la propiedad de contenido XAML para la clase, aplique ContentPropertyAttribute como parte de la definicin de
clase. Especifique el nombre de la propiedad de contenido XAML que desee como Name en el atributo.
Puede especificar una propiedad de coleccin como propiedad de contenido XAML. El resultado es un uso para
esa propiedad mediante la cual el elemento de objeto puede tener uno o ms elementos secundarios, sin
elementos de objeto de coleccin intermedios ni etiquetas de elemento de propiedad. Estos elementos se tratan
entonces como el valor para la propiedad de contenido XAML y se agregan a la instancia de respaldo de la
coleccin.
Algunas propiedades XAML de WPF existentes utilizan el tipo de propiedad de Object. Esto permite que una
propiedad de contenido XAML pueda tomar valores primitivos tales como String as como un valor de objeto de
referencia nico. Si sigue este modelo, el tipo ser responsable de la determinacin de tipo, as como del
control de los tipos posibles. La razn tpica para un modelo de tipo Object es admitir tanto un medio simple
para agregar contenido de objetos en forma de cadena (que recibe un tratamiento de presentacin
predeterminado) como un medio avanzado de agregar contenido de objetos que especifique una presentacin
no predeterminada.
elemento.
Esta
extensin
de
marcado
es
relativamente
compleja,
porque
habilita
una
sintaxis
Una coma siempre representa el separador o el delimitador de token individuales. Por consiguiente una
coma literal no se puede pasar a una extensin de marcado.
Si los token separados individuales no contienen ningn signo igual, cada token se trata como un
argumento de constructor. Cada parmetro de constructor se debe proporcionar como el tipo esperado
por esa firma y en el orden apropiado esperado por esa firma.
Nota:
Un procesador de XAML debe llamar al constructor que coincida con el recuento de argumentos del
nmero de pares. Por esta razn, si est implementando una extensin de marcado personalizada,
Si los token separados individuales contienen signos igual, un procesador de XAML llama primero al
constructor predeterminado para la extensin de marcado. A continuacin, cada par nombre=valor se
interpreta como un nombre de propiedad que existe en la extensin de marcado y un valor que
asignar a esa propiedad.
para
asignar
los
distintos
espacios
de
nombres
comunes,
como
System.Windows
de
INameScope,
FrameworkElement
FrameworkContentElement,
entonces
llamar
RegisterName en cualquier elemento secundario no surtir ningn efecto. Si no crea explcitamente el nuevo
mbito de nombres, al llamar a RegisterName se iniciar una excepcin.
mbitos de nombres en estilos y plantillas
Los estilos y las plantillas de WPF proporcionan la capacidad de reutilizar y aplicar de nuevo el contenido de una
manera sencilla, pero los estilos y las plantillas tambin pueden incluir elementos con nombres definidos en el
nivel de plantilla. Esta misma plantilla se puede utilizar varias veces en una pgina. Por este motivo, los estilos
y las plantillas definen sus propios mbitos de nombres, independientes de la pgina contenedora donde se
aplican dichos estilos y plantillas.
Considere el ejemplo siguiente:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Page.Resources>
<ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
<Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Page.Resources>
<StackPanel>
<Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
<Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
</StackPanel>
</Page>
Aqu, se aplica la misma plantilla a dos botones diferentes. Si las plantillas no tuvieran el mbitos de nombres
discretos, el nombre TheBorder utilizado en la plantilla provocara un conflicto de nombres. Cada instancia que
se crea de la plantilla tiene su propio mbito de nombres, por lo que en este ejemplo el mbito de nombres de
cada instancia de la plantilla contendr exactamente un nombre.
Los estilos tambin obtienen su propio mbito de nombres, principalmente para permitir la asignacin de
nombres concretos a los distintos componentes del guin. Estos nombres habilitan comportamientos concretos
tiene
FrameworkContentElement
poseer
comportamientos
jams
un
anlogos,
mbito
de
con
la
excepcin
nombres.
Los
de
mtodos
que
ningn
existen
en
FrameworkContentElement para que las llamadas se puedan reenviar, en caso necesario, a un elemento
primario FrameworkElement.
SetNameScope se utiliza para asignar un nuevo mbito de nombres a un objeto existente. Puede llamar ms de
una vez a SetNameScope a fin de restablecer o borrar el mbito de nombres, pero no suele hacerse.
GetNameScope tampoco se suele utilizar mediante cdigo.
Implementaciones de mbitos de nombres
Las clases siguientes implementan INameScope directamente:
NameScope
Style
ResourceDictionary
FrameworkTemplate
ResourceDictionary no utiliza mbitos de nombres, sino claves, porque es una implementacin de diccionariotabla hash. La nica razn por la que ResourceDictionary implementa INameScope es para poder iniciar
excepciones en el cdigo de usuario que ayuden a aclarar la distincin entre un mbito de nombres verdadero y
la manera de administrar las claves por parte de ResourceDictionary, adems de asegurarse, en particular, de
que ningn elemento primario aplique mbitos de nombres a ResourceDictionary.
FrameworkTemplate y Style implementan INameScope mediante definiciones de interfaz explcitas. Las
implementaciones explcitas permiten que estos mbitos de nombres se comporten de un modo convencional
cuando se tiene acceso a ellos a travs de la interfaz INameScope, que es el modo que los procesos internos de
WPF utilizan para comunicar los mbitos de nombres. No obstante, las definiciones de interfaz explcitas no
FrameworkElement
FrameworkContentElement
Se quitan los caracteres de avance de lnea entre los caracteres del este asitico. Vea la seccin
Caracteres del este asitico ms adelante en este mismo tema para obtener una definicin del trmino
"caracteres del este asitico".
2.
Todos los caracteres de espacio en blanco (espacio, avance de lnea, tabulacin) se convierten en
espacios.
3.
4.
5.
El "valor predeterminado" corresponde al estado indicado por el valor predeterminado de Control de xml:space
en XAML.
Espacio en blanco en texto interno y primitivas de cadena
Las reglas de la normalizacin anteriores se aplican al texto interno situado dentro de los elementos XAML.
Despus de la normalizacin, un procesador XAML convertir cualquier texto interno en un tipo adecuado, como
se indica a continuacin:
Si el tipo de la propiedad es una coleccin, y el texto interno es contiguo (sin etiquetas de elementos
intermedias), el texto interno se analiza como una sola cadena (String). Si el tipo de coleccin no
puede aceptar String, esto tambin da lugar a un error en tiempo de compilacin.
Si el tipo de la propiedad es Object, el texto interno se analiza como una sola cadena (String). Si hay
etiquetas de elemento intermedias, dar lugar a un error en tiempo de compilacin, porque el tipo
Object implica que hay un objeto nico (de tipo String u otro).
La
combinacin
de
xml:space="default"
de
espacio
en
blanco
dentro
de
CanConvertTo
CanConvertFrom
ConvertTo
ConvertFrom
De ellos, el mtodo ms importante es ConvertFrom. Este mtodo convierte la cadena de entrada en el tipo de
objeto necesario.
El siguiente mtodo en importancia es ConvertTo. Si una aplicacin de WPF se convierte en una representacin
de marcado (por ejemplo, si se guarda en XAML), ConvertTo es responsable de generar una representacin de
marcado.
CanConvertTo y CanConvertFrom son mtodos de compatibilidad que se utilizan cuando un servicio consulta las
funciones de la implementacin de TypeConverter. Debe implementar estos mtodos para devolver true en
algunos casos, en particular para el tipo String.
Implementar un convertidor de tipos
Implementar ConvertFrom
Para poder utilizarlo como una implementacin de TypeConverter que admite XAML, el mtodo ConvertFrom
para ese convertidor debe aceptar una cadena como el parmetro value. Si el formato de la cadena es vlido y
la implementacin de TypeConverter la puede convertir, entonces el objeto devuelto debe ser convertible al tipo
esperado por la propiedad. De lo contrario, la implementacin de ConvertFrom debe devolver null.
Entidad
Notas
& (carcter de Y
comercial)
&
> (carcter
mayor que)
<
< (carcter
menor que)
<
" (carcter de
comillas dobles)
"
' (carcter de
comilla simple)
'
(asignaciones
caracteres
numricos)
&#[entero]; o
&#x[hexadecimal];
(espacio de no
separacin)
  (suponiendo
la codificacin UTF-8)
arrayObject1,arrayObject2,
etc.
Comentarios
Type es un atributo necesario para todos los elementos de objeto x:Array.
La clase ArrayExtension define el control para esta extensin de marcado en la implementacin del procesador
XAML de WPF. Esta clase no es de tipo sealed, y se puede utilizar como base para una implementacin de
extensin de marcado para un tipo de matriz personalizado.
x:Array est pensada ms concretamente para la extensibilidad de lenguaje general en XAML. No obstante,
x:Array tambin puede resultar til para rellenar algunas propiedades mediante XAML que aceptan interfaces o
clases de compatibilidad con colecciones generales como contenido de propiedad estructurado, como
IEnumerable, por ejemplo.
Los elementos de objeto que rellenan una matriz x:Array no suelen existir en el espacio de nombres xmlns de
WPF y requieren una asignacin de prefijo.
Por ejemplo, a continuacin se muestra una matriz simple de dos cadenas, con el prefijo sys (as como x)
definido en el nivel de la matriz:
<x:Array Type="sys:String" xmlns:x= http://schemas.microsoft.com/winfx/2006/xaml
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String>Hello</sys:String>
<sys:String>World</sys:String>
</x:Array>
x:Array es una extensin de marcado. Las extensiones de marcado suelen implementarse cuando se necesita
utilizar valores de atributos que no sean valores literales o nombres de controladores, y se trata de un requisito
global que no se cubre con slo incluir convertidores de tipos en determinados tipos o propiedades. En cierto
<object x:Class="namespace.classname"...>
...
</object>
Valores XAML
namespace
Opcional. Especifica un espacio de nombres CLR que contiene la clase parcial identificada por
classname. Si se especifica namespace, se incluye un punto (.) para separar namespace y
classname.
classname
Necesario. Especifica el nombre CLR de la clase parcial que conecta el XAML cargado y el
cdigo subyacente de ese XAML.
Comentarios
x:Class se puede declarar como atributo para cualquier elemento que sea la raz de un rbol de elementos
Lenguaje de marcado de aplicaciones extensible (XAML) y que se genere (donde Lenguaje de marcado de
aplicaciones extensible (XAML) est incluido en un proyecto con la accin de compilacin Page), o bien para el
objeto Application raz de la definicin de una aplicacin generada. Si se declara x:Class en cualquier elemento
que no sea una raz de pgina o raz de aplicacin, y en cualquier circunstancia para un archivo Lenguaje de
marcado de aplicaciones extensible (XAML) que no est compilado, se producir un error en tiempo de
compilacin.
La clase utilizada como x:Class no puede ser una clase anidada.
x:Class es opcional en el sentido de que es totalmente vlido que una pgina XAML no tenga ningn cdigo
subyacente; sin embargo, si la pgina declara valores de atributos de control de eventos, o crea instancias de
elementos personalizados cuyas clases definidoras se encuentran en la clase de cdigo subyacente, entonces es
obligatorio proporcionar la referencia de x:Class (o x:Subclass) a la clase adecuada para el cdigo subyacente.
El valor del atributo x:Class debe ser una cadena que especifica el nombre completo de una clase. En las
aplicaciones simples, se puede omitir la informacin de espacio de nombres siempre que el cdigo subyacente
tambin est estructurado as (la definicin se inicia en el nivel de clases). El archivo de cdigo subyacente para
una definicin de pgina o de aplicacin debe estar dentro de un archivo de cdigo incluido como parte del
proyecto que genera una aplicacin compilada. Debe respetar las reglas de nombres de las clases CLR; para
obtener detalles, vea los detalles, vea Type Definitions. De manera predeterminada, la clase de cdigo
subyacente debe ser public, pero se puede definir con otro nivel de acceso mediante Atributo x:ClassModifier.
La cadena exacta que se debe pasar para especificar el valor Public en lugar de NonPublic
vara, dependiendo del lenguaje de programacin subyacente que se utilice. Vea Comentarios.
Dependencias
x:Class tambin se debe proporcionar para el mismo elemento, que debe ser el elemento raz de una pgina.
Comentarios
El valor del atributo x:ClassModifier vara segn el lenguaje de programacin. La cadena que hay que utilizar
depende de cmo se implemente CodeDomProvider en el lenguaje, de los convertidores de tipos que se
devuelvan en cada lenguaje para definir los significados de TypeAttributes.Public y TypeAttributes.NonPublic, y
de si ese lenguaje distingue entre maysculas y minsculas o no.
Para C#, la cadena que se debe pasar para designar NonPublic es internal.
Para Microsoft Visual Basic .NET, la cadena que se debe pasar para designar NonPublic es Friend.
Para C++/CLI, en este momento los elementos de destino C++/CLI no admiten la compilacin de
XAML.
Tambin puede especificar Public (public en C#, Public en Microsoft Visual Basic .NET) pero no es frecuente,
porque el comportamiento Public ya es el valor predeterminado.
El valor para Private (private en C#) no es pertinente para x:ClassModifier, porque XAML no admite referencias
a clases anidadas, de modo que el modificador NonPublic tiene el mismo efecto.
La cadena exacta que se debe pasar para especificar el valor Public en lugar de NonPublic vara,
dependiendo del lenguaje de programacin subyacente que se utilice. Vea Comentarios.
Dependencies
x:Name tambin se debe proporcionar en el mismo elemento.
Comentarios
El valor del atributo x:FieldModifier vara segn el lenguaje de programacin. La cadena que hay que utilizar
depende de cmo se implemente CodeDomProvider en el lenguaje, de los convertidores de tipos que se
devuelvan en cada lenguaje para definir los significados de TypeAttributes.Public y TypeAttributes.NonPublic, y
de si ese lenguaje distingue entre maysculas y minsculas o no.
Para C#, la cadena que se debe pasar para designar Public es public.
Para Microsoft Visual Basic .NET, la cadena que se debe pasar para designar Public es Public.
Para C++/CLI, en este momento los elementos de destino C++/CLI no admiten la compilacin de
XAML.
Tambin puede especificar NonPublic (internal en C#, Friend en Microsoft Visual Basic .NET) pero no es
frecuente, porque el comportamiento NonPublic ya es el valor predeterminado.
NonPublic es el valor predeterminado porque es infrecuente que el cdigo externo al ensamblado que ha
compilado el marcado XAML necesite tener acceso a un elemento creado mediante XAML. En la arquitectura de
seguridad de WPF se toma la decisin consciente de no hacer pblicos los campos que almacenan instancias de
elementos a no ser que se establezca especficamente el atributo x:FieldModifier.
Cadena real utilizada como clave, que debe cumplir la Gramtica de XamlName.
O bien,
Extensin de marcado que proporciona un tipo de objeto alternativo que acta como
clave. Vea Comentarios.
Comentarios
En general, los elementos secundarios de un elemento primario que es una implementacin de IDictionary,
como ResourceDictionary, deben incluir un atributo x:Key que especifica un valor de clave nica dentro de ese
diccionario. Las excepciones son Style con la propiedad TargetType o DataTemplate con la propiedad DataType,
ya que ambas tienen su propia clave implcita. La aplicacin de esta singularidad de las claves en el momento
de la carga corre a cargo de la implementacin del procesador XAML de WPF. Los valores de x:Key ausentes o
que no sean nicos producirn errores en tiempo de carga.
El valor de atributo de x:Key puede ser cualquier cadena definida en Gramtica de XamlName, o bien un objeto
evaluado
mediante
una
extensin
de
marcado.
Por
ejemplo,
el
valor
de
x:Key
puede
ser
ComponentResourceKey. Este escenario se utiliza cuando algunos controles exponen una clave de estilo que se
puede utilizar para crear un recurso de estilo personalizado que influye en la apariencia y el funcionamiento de
ese control sin reemplazar el estilo completamente. Un ejemplo de este tipo de clave es ButtonStyleKey.
Observe que, en la sintaxis mostrada, el objeto ResourceDictionary est implcito en la manera en que el
procesador XAML genera una coleccin para rellenar una coleccin Resources, y no se suele proporcionar
explcitamente como un elemento en el marcado, aunque se puede hacer si se desea para aportar mayor
claridad (sera un elemento de objeto de coleccin entre el elemento de propiedad Resources y los elementos
que contiene incluidos en el diccionario).
La clase abstracta ResourceKey define el control para esta extensin de marcado en la implementacin del
procesador XAML de WPF. Sin embargo, el procesador XAML de WPF genera tipos de extensin subyacentes
diferentes para las claves, segn su uso. Por ejemplo, la clave de un objeto DataTemplate o sus clases
derivadas se administra por separado y genera un objeto DataTemplateKey diferenciado.
Las claves y los nombres no son conceptos idnticos y, en realidad, son mutuamente excluyentes segn la
definicin de WPF de estos conceptos.
El equivalente en cdigo de especificar x:Key es la clave usada en cualquier operacin que utiliza una clave con
la interfaz IDictionary subyacente. Por ejemplo, una clave x:Key aplicada en el marcado de un recurso equivale
al valor del parmetro key de ResourceDictionary.Add cuando se agrega el recurso a ResourceDictionary.
Comentarios
El atributo x:Name especificado se convierte en el nombre de un campo creado en el cdigo subyacente al
procesar XAML, y ese campo contiene una referencia al objeto.
De manera predeterminada, el campo creado es interno. Puede cambiar el acceso al campo especificando el
atributo x:FieldModifier.
Para una aplicacin que utiliza destinos de Microsoft Visual Basic .NET e incluye archivos XAML, se crea una
propiedad de referencia independiente durante la compilacin que agrega la palabra clave WithEvents a todos
los elementos que tienen un atributo x:Name, a fin de admitir la sintaxis de Handles para los delegados de
controladores de eventos. Esta propiedad siempre es pblica
x:Name debe ser nico dentro de un mbito de nombres. En los casos de XAML ms comunes, el mbito de
nombres principal se define mediante esos elementos contenidos en una misma pgina XAML. Los mbitos de
nombres adicionales los define cualquier plantilla que tambin est definida en esa pgina.
Un procesador XAML utiliza x:Name para registrar un nombre en un mbito de nombres, incluso en aquellos
casos en que la pgina no est compilada (por ejemplo, XAML dinmico). Esto se debe a que x:Name se
necesita potencialmente para el enlace de ElementName.
x:Name no se puede aplicar en algunos mbitos. Por ejemplo, los elementos de un objeto ResourceDictionary
no pueden tener nombres, porque ya tienen el x:Key (atributo) como su identificador nico.
Las reglas para permitir x:Name, as como la singularidad de los mbitos, se definen en la implementacin del
marco de trabajo subyacente de Windows Presentation Foundation (WPF), que divide los distintos elementos de
marcado en intervalos de NameScope independientes, tales como diccionarios de recursos, el rbol de
elementos lgico, etc.
Algunas aplicaciones del marco de trabajo de WPF podran ser capaces de evitar cualquier uso del atributo
x:Name, porque la propiedad de dependencia Name especificada dentro del espacio de nombres de WPF para
algunas de las clases base importantes (como FrameworkElement/FrameworkContentElement) ya satisface este
mismo propsito. Existen algunos escenarios de XAML y de marco de trabajo comunes donde es necesario tener
acceso mediante cdigo a un elemento que no tiene una propiedad Name, en particular en algunas clases de
respaldo de animaciones y guiones grficos. Por ejemplo, debe especificar x:Name en las escalas de tiempo y
transformaciones creadas en XAML, si piensa hacer referencia a ellas desde el cdigo.
Si Name se define como una propiedad de un elemento, Name y x:Name se pueden utilizar de forma
intercambiable, pero se producir un error si ambos se especifican en el mismo elemento.
El objeto ResourceDictionary que contiene los elementos con x:Shared se debe compilar. El objeto
ResourceDictionary no puede estar dentro de XAML dinmico ni se puede utilizar para temas.
El
objeto
ResourceDictionary
que
contiene
los
elementos
no
se
puede
anidar
en
otro
ResourceDictionary. Por ejemplo, no puede utilizar x:Shared para los elementos de un objeto
ResourceDictionary que est dentro de un Style que ya es un elemento de un ResourceDictionary.
typeName
staticMemberName
Necesario. Nombre del miembro de valor esttico deseado (una constante, una
propiedad esttica, un campo o un valor de enumeracin).
Comentarios
La entidad de cdigo a la que se hace referencia debe ser una de las siguientes:
constante
propiedad esttica
campo
valor de enumeracin
Si se especifica cualquier otra entidad de cdigo, como una propiedad no esttica, da lugar a un error en
tiempo de compilacin.
Se hace referencia a un tipo que existe en Microsoft .NET Framework pero que no forma parte del
espacio de nombres xmlns de WPF. ste es un escenario relativamente comn para utilizar x:Static.
Por ejemplo, puede utilizar una referencia x:Static con un prefijo que se asigna al espacio de nombres
System a fin de hacer referencia a las propiedades estticas de la clase Environment.
Se hace referencia a un tipo que existe en un ensamblado de WPF, pero ese tipo se encuentra dentro
de un espacio de nombres CLR que no se ha asignado con xmlns de manera que forme parte de la
definicin de xmlns de WPF. La asignacin se lleva a cabo mediante definiciones en ese
ensamblado. Los espacios de nombres CLR sin asignar son tpicos para los espacios de nombres CLR
de WPF que no suelen estar pensados para XAML, como System.Windows.Threading.
Puede utilizar referencias de x:Static que no sean directamente el tipo de valor de una propiedad, pero que se
puedan evaluar como ese tipo. Por ejemplo, puede utilizar una referencia de x:Static esttica para obtener un
valor de una enumeracin, o bien fuera de una propiedad esttica como los distintos colores y pinceles
definidos por SystemColors. Las referencias de x:Static se pueden utilizar para establecer cualquier propiedad
en la sintaxis XAML, incluso aqullas que se basen en una propiedad con un tipo de referencia, porque la
administracin real del valor de x:Static una vez evaluado puede variar, segn los comportamientos de los
convertidores de tipos de la propiedad donde se aplica el valor esttico.
La sintaxis de atributo es la que se usa ms a menudo con esta extensin de marcado. El token de cadena que
se proporciona despus de la cadena de identificador x:Static se asigna como valor de Member de la clase de
extensin StaticExtension subyacente.
x:Static se puede utilizar en la sintaxis de elementos de objeto. En este caso, es preciso especificar el valor de
la propiedad Member.
x:Static tambin se puede utilizar en un uso de atributos detallado que especifica la propiedad Member como
un par propiedad=valor:
<object property="{x:Static Member=prefix:typeName.staticMemberName}" .../>
El uso detallado suele ser til para las extensiones que tienen ms de una propiedad que se puede configurar, o
en aquellos casos en que algunas propiedades son opcionales. Dado que x:Static tiene una sola propiedad
configurable, que es obligatoria, este uso detallado no es habitual.
En la implementacin del procesador XAML de WPF, el control para esta extensin de marcado se define
mediante la clase StaticExtension.
x:Static es una extensin de marcado. Las extensiones de marcado se suelen implementar cuando se necesita
que los valores de los atributos de escape no sean valores literales o nombres de controladores, y este requisito
es de ndole ms global que limitarse a colocar los convertidores de tipos en determinados tipos o propiedades.
Todas las extensiones de marcado de XAML utilizan los caracteres { y } en su sintaxis de atributo, que es la
convencin que permite que un procesador XAML reconozca que el atributo se debe procesar mediante una
extensin de marcado.
classname
Necesario. Especifica el nombre CLR de la clase parcial que conecta el XAML cargado
y el cdigo subyacente de ese XAML. Vea Comentarios.
subclassNamespace
Opcional. Puede ser diferente de namespace, siempre que cada espacio de nombres
pueda resolver el otro. Especifica un espacio de nombres CLR que contiene
subclassName. Si se especifica subclassName, se incluye un punto (.) para separar
subclassNamespace y subclassName.
subclassName
Dependencias
Atributo x:Class tambin se debe proporcionar en el mismo elemento, que debe ser el elemento raz de una
pgina.
Comentarios
El uso de x:Subclass est destinado principalmente a los lenguajes que no admiten las declaraciones de clases
parciales.
x:Subclass se puede declarar para cualquier elemento que sea la raz de una pgina Lenguaje de marcado de
aplicaciones extensible (XAML), y/o para la raz de Application en la definicin de aplicacin, que ya tiene
x:Class. Si se declara x:Subclass en cualquier elemento que no sea la raz de una pgina o aplicacin, o se
especifica sin que exista x:Class, se producir un error en tiempo de compilacin.
La creacin de clases derivadas que funcionen correctamente para el escenario x:Subclass es una tarea
bastante compleja. Puede que sea necesario examinar los archivos intermedios (los archivos .g generados en la
carpeta obj del proyecto, con nombres que incorporan los nombres de los archivos .xaml). Estos archivos
intermedios pueden ayudarle a determinar el origen de algunas construcciones de programacin en las clases
parciales combinadas dentro de la aplicacin compilada.
La clase utilizada como x:Subclass no puede ser una clase anidada.
Los controladores de eventos de la clase derivada deben ser de tipo internal override (Friend Overrides en
Microsoft Visual Basic .NET), a fin de invalidar los cdigos auxiliares correspondientes a los controladores que se
crean en la clase intermedia durante la compilacin. De lo contrario, las implementaciones de la clase derivada
ocultaran la implementacin de clase intermedia (prevaleceran sobre ella) y no se invocaran los controladores
de clase intermedios.
Al definir x:Class y x:Subclass , no es preciso proporcionar ninguna implementacin de la clase a la que x:Class
hace referencia. nicamente hay que darle un nombre mediante el atributo x:Class, para que sirva de gua al
compilador en relacin con la clase que se crea en los archivos intermedios (el compilador no elige un nombre
predeterminado en este caso). Puede proporcionar una implementacin de la clase x:Class si lo desea, pero no
es lo habitual cuando se utiliza x:Class y x:Subclass.
typeNameValue
Necesario. Nombre de tipo que se puede resolver para hallar el xmlns predeterminado
actual, o prefijo asignado especificado si se proporciona prefix.
Comentarios
x:Type se utiliza para proporcionar el valor de atributo de una propiedad que acepta Type. Sin embargo,
muchas propiedades que toman Type como valor pueden aceptar directamente el nombre del tipo (el valor de
cadena Type.Name); vea la documentacin de la propiedad concreta para obtener informacin detallada. En
esencia, x:Type es un equivalente de la extensin de marcado para el operador typeof() de C# o para el
operador GetType de Microsoft Visual Basic .NET.
El xmlns predeterminado se define para cualquier pgina XAML determinada como atributo en el elemento raz.
Generalmente, el xmlns predeterminado que se utiliza para la programacin en Windows Presentation
Foundation
(WPF)
es
el
xmlns
XAML
de
WPF.
El
identificador
de
ese
espacio
de
nombres
es
classname
Nombre de los tipos utilizados para restringir la instancia genrica. Los caracteres [
y ] de la sintaxis no son literales, indican que es opcional pasar ms de un tipo a
x:TypeArguments. Si se pasa ms de un tipo, deben separarse entre s mediante
comas (,).
Dependencias
Atributo x:Class tambin se debe proporcionar en el mismo elemento, que debe ser el elemento raz de una
pgina.
Comentarios
Este atributo slo se puede utilizar para el elemento raz, especificando x:Class para ese tipo genrico, y
nicamente cuando ese elemento raz se asigna a un tipo genrico que tiene al menos un argumento de tipo.
Un ejemplo de ello sera PageFunction<(Of <(T>)>).
Si el tipo genrico tiene un solo argumento de tipo, el valor de atributo es una referencia a un solo tipo, el cual
se especifica como valor de atributo mediante la sintaxis de Extensin de marcado x:Type. Si el tipo genrico
tiene varios argumentos de tipo, las diversas referencias de tipo se separan mediante comas dentro del valor
del atributo.
Cadena creada manualmente o generada automticamente que debe ser nica dentro del
archivo cuando la interpretan los procesos o las herramientas de localizacin.
Comentarios
x:Uid es el nico caso excepcional de Lenguaje de marcado de aplicaciones extensible (XAML) en que se
permite que un atributo se encuentre en un elemento de propiedad. Todos los otros atributos no son vlidos en
un elemento de propiedad. Este uso es necesario porque un elemento de propiedad puede contener una
cadena, y la nica manera de marcar esa cadena como un recurso nico que es preciso localizar es colocar el
atributo x:Uid en el elemento de propiedad envolvente.
Necesario. El nico elemento raz de la isla de datos adjunta. Sin una raz nica,
x:XData no es vlido como origen de datos.
[elementData]
Opcional. XML que representa los datos. Cualquier nmero de elementos se puede
contener como datos de elementos, los elementos anidados se pueden contener en
otros elementos, etc., segn las reglas generales de XML.
Dependencias
El elemento x:XData se utiliza principalmente como elemento secundario de XmlDataProvider o bien, como
alternativa, como el elemento secundario de la propiedad XmlSerializer de la propiedad de XmlDataProvider
expresado en sintaxis de propiedades de objeto.
Comentarios
Los elementos XML incluidos en este elemento de directiva pueden volver a declarar todos los posibles espacios
de nombres y prefijos dentro de la isla de datos. Normalmente, los datos deberan volver a definir el xmlns
base dentro de la isla de datos de manera que sea el nuevo xmlns predeterminado (establecido en una cadena
vaca). Es lo ms fcil para las islas de datos simples, porque las expresiones XPath utilizadas para hacer
referencia y enlazar a los datos pueden evitar la inclusin de prefijos. En las islas de datos ms complejas
podran definirse varios prefijos para los datos y utilizarse un prefijo concreto para el xmlns de la raz. En este
caso, todas las referencias a las expresiones XPath debern incluir el prefijo adecuado asignado por el espacio
de nombres.
Tcnicamente, x:XData se pueden utilizar como contenido de cualquier propiedad de tipo IXmlSerializable. Sin
embargo, XmlDataProvider.XmlSerializer es la nica implementacin notable.
Descripcin
Lu
Letra, mayscula
Ll
Letra, minscula
Lt
Letra, ttulo
Lm
Letra, modificador
Lo
Letra, otra
Mn
Marca, de no espaciado
Mc
Nd
Nmero, decimal
Nl
Nmero, letra
XAML define una segunda gramtica, DottedXamlName, que se utiliza para las referencias completas a
propiedades y eventos, as como para los miembros asociados.
Los valores de cadena que son del tipo DottedXamlName deben respetar la gramtica siguiente:
DottedXamlName ::= XamlName '.' XamlName
Comentarios
La secuencia de escape {} se utiliza para evitar el uso de { y } habitual para las extensiones de marcado en la
sintaxis de atributo. La propia secuencia de escape no es estrictamente una extensin de marcado y no est
respaldada por una clase. Todas las dems extensiones de marcado de XAML utilizan los caracteres { y }
reconocidos por las implementaciones del procesador XAML, a fin de permitir mediante una secuencia de
escape el control de valores de atributos que no sean literales o referencias del controlador. Slo el caso
especial de las dos llaves adyacentes se tratar como la secuencia de escape.
Esta secuencia de escape es til para establecer el carcter literal { como el primer carcter de un valor.
Cadena derivada de la norma RFC 3066 que identifica un idioma o bien un idioma y su
regin, separados por un guin.
Comentarios
La definicin para el atributo xml:lang en XAML se deriva de xml:lang, definido como un "atributo especial" por
World Wide Web Consortium (W3C) para XML. Los elementos pueden procesar la informacin de idioma y
referencia cultural de maneras diferentes segn sus implementaciones, pero no existe ningn procesamiento
XAML predeterminado del atributo xml:lang.
El valor predeterminado del atributo xml:lang es una cadena vaca en el nivel de atributo.
El mbito de los efectos de atributo xml:lang y su valor se aplica a los elementos secundarios.
Para los elementos que son clases derivadas de FrameworkElement o FrameworkContentElement, puede utilizar
la propiedad de dependencia Language equivalente, en lugar del atributo xml:lang. La propiedad Language se
establece de manera predeterminada en "en-US" si no se establece de otro modo, ya sea mediante la
propiedad misma o bien procesando el atributo xml:lang.
value
ConverterParameter: si se pasa un tipo por referencia, requiere una referencia a objeto, como una
Extensin de marcado StaticResource.
ElementName: mutuamente excluyente con respecto a RelativeSource, Source; cada una de estas
propiedades representa una metodologa de enlace determinada.
FallbackValue: si se pasa un tipo por referencia, requiere una referencia a objeto, como una Extensin
de marcado StaticResource.
Mode
NotifyOnSourceUpdated
NotifyOnTargetUpdated
NotifyOnValidationError
Path.
RelativeSource: mutuamente excluyente con respecto a ElementName, Source; cada una de estas
propiedades representa una metodologa de enlace determinada.
Source: mutuamente excluyente con respecto a RelativeSource, ElementName; cada una de estas
propiedades representa una metodologa de enlace determinada.
UpdateSourceTrigger
XPath
Las siguientes son propiedades de Binding que no se pueden establecer mediante la extensin de marcado
Binding.
UpdateSourceExceptionFilter
ValidationRules
XmlNamespaceManager
Comentarios
Los marcadores de posicin bindingPropertyName proporcionados aqu corresponden a los nombres de algunas
de las propiedades que se pueden establecer declaradas de la clase Binding y las cadenas de valor son
equivalentes a cmo se estableceran esos valores de propiedades como atributos XAML dentro de un objeto
Binding declarado como un elemento XAML.
La explicacin de sintaxis alternativas incluye cmo crear enlaces equivalentes en varias sintaxis posibles, tales
como las propiedades de atributo de un elemento de objeto Binding en XAML, la sintaxis de elementos de
propiedad de Binding, o la creacin mediante procedimiento de un enlace utilizando el mtodo SetBinding o el
constructor Binding.
Nota importante:
Por lo que se refiere a la prioridad de las propiedades de dependencia, una expresin Binding es
equivalente a un valor establecido localmente. Si establece un valor local para una propiedad que
previamente tena una expresin Binding, Binding se quita totalmente.
Nota:
MultiBinding y PriorityBinding no admiten la sintaxis de extensiones XAML (aunque comparten la misma
clase BindingBase, que en realidad implementa el comportamiento de XAML para Binding).
Binding es una extensin de marcado. Las extensiones de marcado se suelen implementar cuando se necesita
que los valores de los atributos de escape no sean valores literales o nombres de controladores, y este requisito
es de ndole ms global que limitarse a colocar los convertidores de tipos en determinados tipos o propiedades.
Todas las extensiones de marcado de XAML utilizan los caracteres { y } en su sintaxis de atributo, que es la
convencin que permite que un procesador XAML reconozca que el atributo se debe procesar mediante una
extensin de marcado. Para obtener ms informacin, consulte Extensiones de marcado y XAML. Binding es
una extensin de marcado inusual porque la clase Binding que implementa la funcionalidad de la extensin
tambin implementa otros mtodos y propiedades. Estos otros miembros no constituyen un requisito directo
para la funcionalidad de la extensin de marcado. Estos miembros estn dirigidos a aumentar la versatilidad y
autonoma de la clase Binding para que sea capaz de resolver numerosos escenarios de enlace de datos
adems de actuar como extensin de marcado XAML.
sourceIIC
destinationIIC
Comentarios
Esta extensin de marcado se ha diseado para rellenar un conjunto relacionado de valores de propiedades del
origen de la imagen, como UriSource.
La sintaxis de atributo es la que se usa ms a menudo con esta extensin de marcado. ColorConvertedBitmap
(o ColorConvertedBitmapExtension) no se puede utilizar en la sintaxis de elementos de propiedad, porque los
valores nicamente se pueden establecer como tales en el constructor inicial, que es la cadena que sigue al
identificador de la extensin.
ColorConvertedBitmap es una extensin de marcado. Las extensiones de marcado se suelen implementar
cuando se necesita que los valores de los atributos de escape no sean valores literales o nombres de
controladores, y este requisito es de ndole ms global que limitarse a colocar los convertidores de tipos en
determinados tipos o propiedades. Todas las extensiones de marcado de XAML utilizan los caracteres { y } en
su sintaxis de atributo, que es la convencin que permite que un procesador XAML reconozca que el atributo se
debe procesar mediante una extensin de marcado.
Nombre del tipo common language runtime (CLR) pblico definido en el ensamblado de
recursos.
targetID
Clave del recurso. Al buscar los recursos, targetID ser anlogo al x:Key (atributo) del
recurso.
Comentarios
TypeInTargetAssembly identifica un tipo que existe como tal en el ensamblado de destino donde el recurso est
definido en realidad. ComponentResourceKey se puede definir y utilizar independientemente de si se sabe con
Clave del recurso solicitado. Esta clave la asigna x:Key inicialmente si se ha creado un recurso en el
marcado, o bien se proporciona como parmetro key al llamar a ResourceDictionary.Add si el recurso
se ha creado mediante cdigo.
Comentarios
Un DynamicResource crear una expresin temporal durante la compilacin inicial y, de este modo, diferir la
consulta de recursos hasta que el valor de recurso solicitado se necesite realmente para construir un objeto.
Potencialmente, esto puede suceder una vez cargada la pgina XAML. El valor de recurso se buscar mediante
la bsqueda de clave en todos los diccionarios de recursos activos empezando por el mbito de la pgina
actual, y reemplazar la expresin utilizada como marcador de posicin en la compilacin.
Nota importante:
Por lo que se refiere a la prioridad de las propiedades de dependencia, una expresin DynamicResource es
equivalente a la posicin donde se aplica la referencia dinmica al recurso. Si establece un valor local para
una propiedad que previamente tena una expresin DynamicResource como su valor local,
DynamicResource se quita totalmente.
Algunos escenarios de acceso a recursos son particularmente adecuados para DynamicResource al contrario
que una Extensin de marcado StaticResource.
La propiedad ResourceKey especificada debe corresponder a un recurso existente determinado por x:Key
(atributo) en algn nivel de la pgina, la aplicacin, los temas de control disponibles y los recursos externos o
recursos del sistema, y la bsqueda de recursos se realizar en ese orden.
Una clave de recurso puede ser cualquier cadena definida en Gramtica de XamlName. Una clave de recurso
tambin puede ser otros tipos de objeto, como un Type. Una clave Type es fundamental para el modo de
aplicar estilos a los controles mediante temas.
Las API para la bsqueda de valores de recursos, como FindResource, siguen la misma lgica de bsqueda de
recursos que DynamicResource.
La manera declarativa alternativa de hacer referencia a un recurso es hacerlo como Extensin de marcado
StaticResource.
La sintaxis de atributo es la que se usa ms a menudo con esta extensin de marcado. El token de cadena que
se proporciona despus de la cadena de identificador DynamicResource se asigna como valor de ResourceKey
de la clase de extensin DynamicResourceExtension subyacente.
DynamicResource se puede utilizar en sintaxis de elementos de objeto. En este caso, es preciso especificar el
valor de la propiedad ResourceKey.
DynamicResource tambin se puede utilizar en un uso de atributos detallado que especifica la propiedad
ResourceKey como un par propiedad=valor:
<object property="{DynamicResource ResourceKey=key}" .../>
El uso detallado suele ser til para las extensiones que tienen ms de una propiedad que se puede configurar, o
en aquellos casos en que algunas propiedades son opcionales. Dado que DynamicResource tiene una sola
propiedad configurable, que es obligatoria, este uso detallado no es habitual.
La clase DynamicResourceExtension define el control para esta extensin de marcado en la implementacin del
procesador XAML de WPF.
DynamicResource es una extensin de marcado. Las extensiones de marcado se suelen implementar cuando se
necesita que los valores de los atributos de escape no sean valores literales o nombres de controladores, y este
requisito es de ndole ms global que limitarse a colocar los convertidores de tipos en determinados tipos o
propiedades. Todas las extensiones de marcado de XAML utilizan los caracteres { y } en su sintaxis de atributo,
que es la convencin que permite que un procesador XAML reconozca que el atributo se debe procesar
mediante una extensin de marcado.
FindAncestor
typeName
intLevel
Opcional para el modo FindAncestor. Un nivel del antecesor (se evala en la direccin
del elemento primario en el rbol lgico).
Comentarios
En la sintaxis de elementos de objeto para el modo FindAncestor que se muestra anteriormente, la segunda
sintaxis de elementos de objeto se utiliza especficamente para el modo FindAncestor. El modo FindAncestor
requiere un valor de AncestorType. Debe establecer AncestorType como atributo utilizando una referencia de
Extensin de marcado x:Type al tipo de antecesor que se desea buscar. Se utiliza el valor AncestorType al
procesar la solicitud de enlace en tiempo de ejecucin.
Para el modo FindAncestor, la propiedad AncestorLevel opcional puede ayudar a eliminar la ambigedad en la
bsqueda del antecesor en aquellos casos en que sea posible que exista ms de un antecesor de ese tipo en el
rbol de elementos.
La clase RelativeSource define el control para esta extensin de marcado en la implementacin del procesador
XAML de WPF.
RelativeSource es una extensin de marcado. Las extensiones de marcado se suelen implementar cuando se
necesita que los valores de los atributos de escape no sean valores literales o nombres de controladores, y este
requisito es de ndole ms global que limitarse a colocar los convertidores de tipos en determinados tipos o
propiedades. Todas las extensiones de marcado de XAML utilizan los caracteres { y } en su sintaxis de atributo,
que es la convencin que permite que un procesador XAML reconozca que el atributo se debe procesar
mediante una extensin de marcado.
Clave del recurso solicitado. Esta clave la asigna x:Key (atributo) inicialmente si se ha creado un
recurso en el marcado, o bien se proporciona como parmetro key al llamar a Add si el recurso se ha
creado mediante cdigo.
Comentarios
Nota importante:
StaticResource no debe intentar realizar una referencia adelantada a un recurso que se define lxicamente
en un punto posterior del archivo XAML. Esto no se admite, e incluso si una referencia de este tipo no da
lugar a ningn error, el intento de hacerla provocar una reduccin del rendimiento en tiempo de carga
cuando se busque en las tablas de hash internas que representan un objeto ResourceDictionary. Para
obtener los mejores resultados, ajuste la composicin de los diccionarios de recursos de modo que se
eviten las referencias adelantadas. Si no puede evitar una referencia adelantada, utilice la Extensin de
marcado DynamicResource en su lugar.
La propiedad ResourceKey especificada debe corresponder a un recurso existente, identificado con un x:Key
(atributo) en algn nivel de la pgina, la aplicacin, los temas de control disponibles y los recursos externos o
del sistema. La bsqueda de recursos se produce en ese orden.
Una clave de recurso puede ser cualquier cadena definida en Gramtica de XamlName. Una clave de recurso
tambin puede ser otros tipos de objeto, como un Type. Una clave Type es fundamental para determinar cmo
se pueden aplicar los estilos a los controles mediante temas, a travs de una clave de estilo implcita.
La manera declarativa alternativa de hacer referencia a un recurso es hacerlo como Extensin de marcado
DynamicResource.
La sintaxis de atributo es la que se usa ms a menudo con esta extensin de marcado. El token de cadena que
se proporciona despus de la cadena de identificador StaticResource se asigna como valor de ResourceKey de
la clase de extensin StaticResourceExtension subyacente.
StaticResource se puede utilizar en la sintaxis de elementos de objeto. En este caso, es preciso especificar el
valor de la propiedad ResourceKey.
StaticResource tambin se puede utilizar en un uso de atributos detallado que especifica la propiedad
ResourceKey como un par propiedad=valor:
<object property="{StaticResource ResourceKey=key}" .../>
El uso detallado suele ser til para las extensiones que tienen ms de una propiedad que se puede configurar, o
en aquellos casos en que algunas propiedades son opcionales. Dado que StaticResource tiene una sola
propiedad configurable, que es obligatoria, este uso detallado no es habitual.
La clase StaticResourceExtension define el control para esta extensin de marcado en la implementacin del
procesador XAML de WPF.
targetProperty
Propiedad de dependencia que existe en el tipo con plantilla, especificada por el valor de
DependencyProperty.Name.
O bien,
Un nombre de propiedad "relacionada" que se define por un tipo diferente que el tipo de
destino de la plantilla. En realidad, se trata de un objeto PropertyPath.
Comentarios
TemplateBinding es una forma optimizada de enlace para los escenarios de plantilla, anlogo a la instruccin
Binding construida con {Binding RelativeSource={RelativeSource TemplatedParent}}.
RelativeSource es otra extensin de marcado que se utiliza a veces en combinacin con TemplateBinding o en
su lugar para realizar enlaces de propiedades relativos dentro de una plantilla.
La sintaxis de atributo es la que se usa ms a menudo con esta extensin de marcado. El token de cadena que
se proporciona despus de la cadena de identificador TemplateBinding se asigna como valor de Property de la
clase de extensin TemplateBindingExtension subyacente.
Podra argumentarse que la sintaxis de elementos de objeto es posible, pero no se muestra porque no tiene
ninguna aplicacin realista. TemplateBinding se utiliza para rellenar los valores dentro de los establecedores,
mediante expresiones evaluadas, y el uso de la sintaxis de elementos de objeto para que TemplateBinding
rellene la sintaxis de elementos de propiedad de <Setter.Property> aplica un grado de detalle innecesario.
TemplateBinding tambin se puede utilizar en el uso de atributos detallado que especifica la propiedad Property
como un par de propiedad=valor:
<object property="{TemplateBinding Property=targetProperty}" .../>
El uso detallado suele ser til para las extensiones que tienen ms de una propiedad que se puede configurar, o
en aquellos casos en que algunas propiedades son opcionales. Dado que TemplateBinding tiene una sola
propiedad configurable, que es obligatoria, este uso detallado no es habitual.
La clase TemplateBindingExtension define el control para esta extensin de marcado en la implementacin del
procesador XAML de WPF.
TemplateBinding es una extensin de marcado. Las extensiones de marcado se suelen implementar cuando se
necesita que los valores de los atributos de escape no sean valores literales o nombres de controladores, y este
requisito es de ndole ms global que limitarse a colocar los convertidores de tipos en determinados tipos o
propiedades. Todas las extensiones de marcado de XAML utilizan los caracteres { y } en su sintaxis de atributo,
identificador de recursos uniforme (URI) del ensamblado que contiene informacin del tema.
Normalmente, se trata de un pack URI que hace referencia a un ensamblado en el paquete
mayor. Los recursos de ensamblado y los pack URI simplifican los problemas de
implementacin.
Comentarios
Extensin
est
pensada
para
rellenar
un
solo
valor
de
propiedad
concreto:
un
valor
para
ResourceDictionary.Source.
Utilizando esta extensin, puede especificar un nico ensamblado slo de recursos que contenga algunos estilos
para utilizarlos solamente cuando se aplique el tema Aero de Windows al sistema del usuario, otros estilos
cuando est activo el tema Luna, y as sucesivamente. Utilizando esta extensin, se puede invalidar
automticamente y volver a cargar el contenido de un diccionario de recursos especfico del control de modo
que sea especfico de otro tema cuando se necesite.
La cadena assemblyUri (valor de la propiedad AssemblyName) constituye la base de una convencin de
nomenclatura que identifica qu diccionario se aplica para un tema concreto. La lgica de ProvideValue para
ThemeDictionary completa la convencin generando un identificador de recursos uniforme (URI) que seala a
una variante concreta del diccionario del tema, contenida dentro de un ensamblado de recursos precompilado.
En este artculo no se aborda plenamente la descripcin de esta convencin ni el concepto de las interacciones
de los temas con la aplicacin general de estilos, a controles o en el nivel de aplicacin o pgina. El escenario
bsico para utilizar ThemeDictionary es especificar la propiedad Source de un objeto ResourceDictionary
declarado en el nivel de la aplicacin. Cuando se proporciona un URI para el ensamblado mediante una
extensin de ThemeDictionary en lugar de utilizar un URI directo, la lgica de la extensin proporciona la lgica
de invalidacin que se aplica cada vez que cambia el tema del sistema.
La sintaxis de atributo es la que se usa ms a menudo con esta extensin de marcado. El token de cadena que
se proporciona despus de la cadena de identificador ThemeDictionary se asigna como valor de AssemblyName
de la clase de extensin ThemeDictionaryExtension subyacente.
ThemeDictionary tambin se puede utilizar en la sintaxis de elementos de objeto. En este caso, es preciso
especificar el valor de la propiedad AssemblyName.
ThemeDictionary tambin se puede utilizar en un uso de atributos detallado que especifica la propiedad Member
como un par propiedad=valor:
<object property="{ThemeDictionary AssemblyName=assemblyUri}" .../>
El uso detallado suele ser til para las extensiones que tienen ms de una propiedad que se puede configurar, o
en aquellos casos en que algunas propiedades son opcionales. Dado que ThemeDictionary tiene una sola
propiedad configurable, que es obligatoria, este uso detallado no es habitual.
La ruta de acceso se especifica en XAML, que est en un estilo o plantilla que no tiene un tipo de
destino especificado. Generalmente, un uso certificado no es vlido para otros casos distintos de ste,
porque en los casos sin estilo ni plantilla la propiedad existe en una instancia, no en un tipo.
Para el uso como destino del guin grfico, la propiedad especificada como propertyName debe ser un objeto
DependencyProperty.
Exploracin transversal de origen (enlace a jerarquas de colecciones)
<object Path="propertyName/propertyNameX" .../>
El carcter / de esta sintaxis se utiliza para navegar dentro de un objeto de origen de datos jerrquico; se
admiten varios pasos en la jerarqua con caracteres / sucesivos. La exploracin transversal de origen tiene en
cuenta la posicin del puntero de registro actual, que se determina sincronizando los datos con la interfaz de
usuario de su vista.
Nota:
Superficialmente, esta sintaxis se parece a XPath. Una expresin XPath verdadera para enlazar a un origen
de datos XML no se utiliza como un valor Path y se debe utilizar en su lugar para la propiedad XPath
mutuamente excluyente.
Indizadores mltiples
<object Path="[index1,index2...]" .../>
para
los
usos
de
enlace,
donde
el
objeto
es
una
cadena.
Utilice
la
firma
Utilice
la
firma
PropertyPath(String,
array<Object>[]()[])
para
las
animaciones
complejas. Este ltimo constructor utiliza una cadena de token para el primer parmetro y una matriz de
objetos que rellenan posiciones en la cadena de token para definir una relacin de ruta de acceso de propiedad.
Un prefijo de xmlns, que puede ser cualquier cadena del prefijo vlida, conforme con
la especificacin XML 1.0. El prefijo PresentationOptions se utiliza con fines de
identificacin en esta documentacin.
freezableElement
ignorableUri
ThisElementCanBeIgnored
Comentarios
El prefijo de espacio de nombres mc de XML es la convencin de prefijo recomendada para su uso al asignar el
espacio
de
nombres
de
compatibilidad
con
XAML,
http://schemas.openxmlformats.org/markup-
compatibility/2006.
Los elementos o atributos cuya parte del prefijo del nombre de elemento se identifique como mc:Ignorable no
provocarn errores al procesarlos en un procesador XAML. Si ese atributo no se pudo resolver como un tipo
subyacente o una construccin de programacin, el elemento se omite. Sin embargo, tenga en cuenta que los
ignorableUri
ThisElementCanBeIgnored
[content]
Si crea una clase que se deriva de UIElement, adems de la funcionalidad proporcionada por DependencyObject
heredar la siguiente:
Si crea una clase que se deriva de FrameworkElement, adems de la funcionalidad proporcionada por
UIElement heredar la siguiente:
Si crea una clase que se deriva de ContentElement, adems de la funcionalidad proporcionada por
DependencyObject heredar la siguiente:
Si crea una clase que se deriva de FrameworkContentElement, adems de la funcionalidad proporcionada por
ContentElement obtendr la siguiente:
No se hereda el acceso a las modificaciones del sistema de diseo (como ArrangeOverride). Las
implementaciones del sistema de diseo nicamente estn disponibles en FrameworkElement. Sin
embargo, s heredar una invalidacin de OnPropertyChanged capaz de detectar los cambios de
propiedades que influyen en el diseo y comunicrselas a cualquier host de contenido.
Se documentan modelos de contenido para gran variedad de clases. El modelo de contenido de una clase es
uno de los factores posibles que deben tenerse en cuenta al buscar la clase adecuada para derivarla.
Otras clases base
DispatcherObject
DispatcherObject proporciona compatibilidad con el modelo de subprocesos de WPF y permite asociar todos los
objetos creados para aplicaciones de WPF a Dispatcher. Aunque no se derive de UIElement, DependencyObject
o de Visual, puede ser conveniente derivar de DispatcherObject para obtener esta compatibilidad con el modelo
de subprocesos.
Visual
Si estas condiciones no se cumplen y tampoco tiene previsto modificar un objeto Freezable, entonces es
conveniente inmovilizarlo para obtener las ventajas de rendimiento descritas anteriormente.
PresentationOptions
es
el
prefijo
Clonacin fcil: la clase Freezable ya ha implementado varios mtodos que generan clones perfectos.
CloneCore
CloneCurrentValueCore
GetAsFrozenCoree
GetCurrentValueAsFrozenCore
FreezeCore
Tambin debe observar las reglas siguientes para obtener acceso a los miembros de datos que no son
propiedades de dependencia y escribir en ellos:
Al principio de cualquier API que lee miembros de datos de propiedades que no son de dependencia,
llame al mtodo ReadPreamble.
Al principio de cualquier API que escribe miembros de datos de propiedades que no son de
dependencia, llame al mtodo WritePreamble. (Despus de llamar al mtodo WritePreamble de una
API, ya no necesita realizar una llamada adicional a ReadPreamble si tambin va a leer miembros de
datos de propiedades que no son de dependencia.)
Llame al mtodo WritePostscript antes de salir de los mtodos que escriben en los miembros de datos
de propiedades que no son de dependencia.
Si la clase contiene miembros de datos de propiedades que no son de dependencia y que son objetos
DependencyObject, tambin debe llamar al mtodo OnFreezablePropertyChanged cada vez que cambie uno de
sus valores, aunque establezca el miembro en null.
Nota:
Es muy importante que comience cada mtodo de Freezable que invalide con una llamada a la
implementacin base.
A primera vista, podra parecer que los elementos Button de esta ilustracin estn colocados de forma
aleatoria. Sin embargo, sus posiciones estn controladas precisamente por medio de una combinacin de
mrgenes, alineaciones y relleno.
En el ejemplo siguiente se describe cmo crear el diseo de la ilustracin anterior. Un elemento Border
encapsula un elemento StackPanel primario, con un valor Padding de 15 pxeles independientes del dispositivo.
Nota:
Las propiedades Height y Width establecidas explcitamente en un elemento tienen prioridad sobre el valor
de propiedad Stretch. Al intentar establecer Height, Width y HorizontalAlignment en un valor de Stretch, la
solicitud de Stretch se pasa por alto.
Propiedad HorizontalAlignment
La propiedad HorizontalAlignment declara las caractersticas de alineacin horizontal que se aplican a los
elementos secundarios. En la tabla siguiente se muestra cada uno de los valores posibles de la propiedad
HorizontalAlignment.
Miembro
Descripcin
Left
Center
Los elementos secundarios se alinean al centro del espacio de diseo asignado del
elemento primario.
Right
Stretch (valor
predeterminado)
Propiedad VerticalAlignment
La propiedad VerticalAlignment describe las caractersticas de alineacin vertical que se aplican a los elementos
secundarios. En la tabla siguiente se muestra cada uno de los valores posibles para la propiedad
VerticalAlignment.
Miembro
Descripcin
Top
Los elementos secundarios se alinean con la parte superior del espacio de diseo
asignado del elemento primario.
Center
Los elementos secundarios se alinean al centro del espacio de diseo asignado del
elemento primario.
Bottom
Los elementos secundarios se alinean con la parte inferior del espacio de diseo
asignado del elemento primario.
Stretch (valor
predeterminado)
Pasos adicionales
Las propiedades de posicin definidas por la clase FrameworkElement proporcionan un control preciso de la
posicin de los elementos en las aplicaciones WPF. Ahora dispone de varias tcnicas que puede utilizar para
colocar mejor los elementos mediante WPF.
Si estas condiciones son false para el objeto Freezable y no piensa modificarlo, puede inmovilizarlo para
obtener mejoras de rendimiento.
Ejemplo
En el ejemplo siguiente se inmoviliza un objeto SolidColorBrush, que es un tipo de objeto Freezable.
Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
if (myBrush.CanFreeze)
{
// Makes the brush unmodifiable.
myBrush.Freeze();
}
myButton.Background = myBrush;
Como puede observar en la ilustracin anterior, el botn se ha volteado, pero tambin se ha movido. Esto se
debe a que se volte desde su esquina superior izquierda. Para voltear el botn en su lugar, se debe aplicar
ScaleTransform a su centro, no a su esquina. Una manera fcil de aplicar ScaleTransform al centro de los
botones es establecer la propiedad RenderTransformOrigin del botn en 0.5, 0.5.
<Button Content="Flip me!" Padding="5"
RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<ScaleTransform ScaleX="-1" />
</Button.RenderTransform>
</Button>
El botn con su propiedad RenderTransformOrigin establecida en 0.5, 0.5
Ejemplo
Ajustar los elementos de men antes de la presentacin
Ajustar los elementos de men existentes es bastante simple y, probablemente, es el escenario ms comn.
Puede hacerlo para agregar o quitar opciones en el men contextual en respuesta a la informacin de estado
actual de la aplicacin, o a la informacin de estado concreta disponible como una propiedad del objeto en que
se solicita el men contextual.
La tcnica general consiste en obtener el origen del evento, que es el control concreto donde que se hizo clic
con el botn secundario, y obtener la propiedad ContextMenu de l. Suele ser conveniente comprobar la
coleccin Items para ver qu elementos de men contextual existen ya en ella y, a continuacin, agregar o
quitar los elementos MenuItem nuevos en la coleccin.
void AddItemToCM(object sender, ContextMenuEventArgs e)
{
//check if Item4 is already there, this will probably run more than once
FrameworkElement fe = e.Source as FrameworkElement;
ContextMenu cm = fe.ContextMenu;
foreach (MenuItem mi in cm.Items)
{
if ((String)mi.Header == "Item4") return;
}
MenuItem mi4 = new MenuItem();
mi4.Header = "Item4";
fe.ContextMenu.Items.Add(mi4);
}
Reemplazar el men completo antes de la presentacin
Un escenario alternativo es aqul en que se desea reemplazar el men contextual completo. Por supuesto,
puede utilizar una variacin del cdigo anterior para quitar todos los elementos de un men contextual
existente y agregar otros nuevos partiendo del elemento cero. Pero el enfoque ms intuitivo para reemplazar
todos los elementos del men contextual es crear un nuevo ContextMenu, rellenarlo con elementos y, a
continuacin, establecer la propiedad ContextMenu de un control en el nuevo ContextMenu.
A continuacin, se muestra el cdigo de controlador simple para reemplazar un ContextMenu. En el cdigo se
hace referencia a un mtodo BuildMenu personalizado que est separado porque lo llaman ms de uno de los
controladores del ejemplo.
void HandlerForCMO(object sender, ContextMenuEventArgs e)
{
FrameworkElement fe = e.Source as FrameworkElement;
fe.ContextMenu = BuildMenu();
}
ContextMenu BuildMenu()
{
}
Sin embargo, si utiliza este estilo de controlador para un evento ContextMenuOpening, potencialmente puede
exponer un problema de control de tiempo si el objeto donde se establece el ContextMenu no tiene un men
contextual preexistente. Cuando un usuario hace clic con el botn secundario en un control, se provoca el
evento ContextMenuOpening aunque el objeto ContextMenu existente est vaco o sea null. Sin embargo, en
este caso, sea cual fuere el nuevo ContextMenu que se establezca en el elemento de origen llega demasiado
tarde para mostrarlo. Adems, si el usuario hace clic con el botn secundario por segunda vez, esta vez
aparece el nuevo ContextMenu, su valor no es null y el controlador se reemplaza correctamente y muestra el
men cuando el controlador se ejecuta por segunda vez. Esto sugiere dos posibles soluciones alternativas:
1.
2.
normalmente suele ser conveniente asignar un ContextMenu marcador de posicin en el marcado inicial:
<StackPanel>
<Rectangle Fill="Yellow" Width="200" Height="100" ContextMenuOpening="HandlerForCMO">
<Rectangle.ContextMenu>
<ContextMenu>
<MenuItem>Initial menu; this will be replaced ...</MenuItem>
</ContextMenu>
</Rectangle.ContextMenu>
</Rectangle>
<TextBlock>Right-click the rectangle above, context menu gets replaced</TextBlock>
</StackPanel>
Supongamos que el valor de ContextMenu inicial sea null, segn alguna parte de la lgica preliminar.
Podra comprobar si ContextMenu es null o utilizar un marcador en el cdigo para comprobar si el
controlador se ha ejecutado al menos una vez. Dado que se supone que ContextMenu est a punto de
mostrarse, a continuacin el controlador establece Handled en true en los datos de evento. Para el
ContextMenuService responsable de la presentacin del men contextual, un valor true para Handled en
los datos de evento representa una solicitud de cancelar la presentacin correspondiente a la combinacin
de men contextual y control que provoc el evento.
Ahora que ha suprimido el men contextual que podra mostrarse, el paso siguiente es proporcionar uno nuevo
y mostrarlo. Establecer el nuevo es bsicamente igual que con el controlador anterior: se genera un nuevo
ContextMenu y se establece en l la propiedad ContextMenu del origen del control. La operacin adicional
consiste en forzar ahora la presentacin del men contextual, porque se ha suprimido el primer intento. Para
forzar la presentacin, se establece la propiedad Popup.IsOpen en true dentro del controlador. Extreme las
precauciones al hacerlo, porque al abrir el men contextual en el controlador se provoca de nuevo el evento
ContextMenuOpening. Si entra de nuevo en el controlador, se vuelve infinitamente recursivo. Por este motivo,
siempre hay que comprobar si existe el valor null o utilizar un marcador al abrir un men contextual desde el
interior de un controlador de eventos de ContextMenuOpening.
Suprimir cualquier men contextual existente y no mostrar ninguno
El ltimo escenario, escribir un controlador que suprime un men totalmente, es infrecuente. Si un control no
est pensado para mostrar un men contextual, es probable que existan maneras ms adecuadas de
asegurarse de ello que suprimir el men slo cuando un usuario lo solicita. Sin embargo, si desea utilizar el
controlador para suprimir un men contextual y no presentar nada, entonces el controlador debe limitarse a
establecer Handled en true en los datos de evento. El ContextMenuService responsable de mostrar un men
contextual comprobar los datos del evento que se provoc en el control. Si el evento est marcado como
Salida vectorial o grfica: la salida del rea representada se puede utilizar para reproducir el mismo
vector o grfico al volver a cargarla.
if (value==null) {
RemoveLogicalChild(_child);
} else {
if (_child==null) {
_child = value;
} else {
// raise an exception?
MessageBox.Show("Needs to be a single element");
}
}
}
}
public void SetSingleChild(object child)
{
this.AddLogicalChild(child);
}
public new void AddLogicalChild(object child)
{
_child = (FrameworkElement)child;
if (this.Children.Count == 1)
{
this.RemoveLogicalChild(this.Children[0]);
this.Children.Add((UIElement)child);
}
else
{
this.Children.Add((UIElement)child);
}
}
public new void RemoveLogicalChild(object child)
{
_child = null;
this.Children.Clear();
}
protected override IEnumerator LogicalChildren
{
get {
// cheat, make a list with one member and return the enumerator
ArrayList _list = new ArrayList();
_list.Add(_child);
return (IEnumerator) _list.GetEnumerator();}
}
3.5. Propiedades
Windows Presentation Foundation (WPF) proporciona un conjunto de servicios que se pueden utilizar para
extender la funcionalidad de una propiedad de common language runtime (CLR). Colectivamente, estos
servicios se conocen como el sistema de propiedades de WPF. Una propiedad que est respaldada por el
sistema de propiedades de WPF se conoce como una propiedad de dependencia.
Contenedor
CLR:
implementaciones
reales
de
lectura
escritura
de
la
propiedad.
Estas
propiedades
de
dependencia
la
clase
DependencyObject
no
admiten
de
forma
nativa
Una propiedad asociada es un tipo de propiedad que admite una sintaxis especializada en XAML. Una
propiedad asociada no suele tener una correspondencia 1:1 con una propiedad de common language
runtime (CLR) y no es necesariamente una propiedad de dependencia. El propsito tpico de una
propiedad asociada es permitir que los elementos secundarios informen de los valores de la propiedad
a un elemento primario, aunque el elemento primario y los elementos secundarios no posean esa
propiedad como parte de las listas de miembros de la clase. Un escenario primario consiste en permitir
que los elementos secundarios informen el elemento primario de cmo se deben presentar en interfaz
de usuario.
El tipo que define la propiedad asociada se ha diseado de modo que pueda ser el elemento primario
de los elementos que establecern los valores de la propiedad asociada. El tipo recorre a continuacin
sus elementos secundarios mediante lgica interna, obtiene los valores y acta sobre esos valores de
alguna manera.
El tipo que define la propiedad asociada se utilizar como elemento secundario para una variedad de
posibles elementos principales y modelos de contenido.
El tipo que define la propiedad asociada representa un servicio. Otros tipos establecen valores para la
propiedad asociada. A continuacin, cuando el elemento que estableci la propiedad se evala en el
contexto del servicio, los valores de la propiedad asociada se obtienen a travs de lgica interna de la
clase de servicio.
El objeto target se puede especificar como un tipo ms especfico en la implementacin. Por ejemplo,
el mtodo DockPanel.GetDock establece el tipo del parmetro como UIElement, porque la propiedad
asociada solamente est destinada a establecerse en instancias de UIElement.
El valor devuelto se puede especificar como un tipo ms especfico en la implementacin. Por ejemplo,
el mtodo GetDock define el tipo como Dock, porque el valor solamente se puede establecer en esa
enumeracin.
El objeto target se puede especificar como un tipo ms especfico en la implementacin. Por ejemplo,
el mtodo SetDock establece el tipo como UIElement, porque la propiedad asociada solamente est
destinada a establecerse en instancias de UIElement.
El objeto value se puede especificar como un tipo ms especfico en la implementacin. Por ejemplo, el
mtodo SetDock define el tipo como Dock, porque el valor solamente se puede establecer en esa
enumeracin. Recuerde que el valor para este mtodo es la entrada procedente del cargador de XAML
cuando encuentra la propiedad asociada en un uso de propiedad asociada en el marcado. Esa entrada
es el valor especificado como valor de atributo XAML en el marcado. Por consiguiente, debe haber
compatibilidad con conversin de tipos, serializador de valor o extensin de marcado para el tipo que
se utilice, de modo que se pueda crear el tipo adecuado a partir del valor del atributo (que, en ltima
instancia, no es nada ms que una cadena).
expuesta
por
una
clase
tiene
un
campo
esttico
pblico
correspondiente
de
tipo
Desea que su propiedad pueda establecerse con una referencia de recurso dinmico.
Desea heredar automticamente el valor de una propiedad de un elemento primario del rbol de
elementos. En este caso, efecte el registro con el mtodo RegisterAttached, incluso aunque tambin
cree un contenedor de propiedades para el acceso de CLR.
Desea que el sistema de propiedades notifique el momento en el que cambie el valor anterior de la
propiedad mediante acciones realizadas por el sistema de propiedades, el entorno o el usuario, o
mediante la lectura y el uso de estilos. El uso de metadatos de propiedad permite que su propiedad
especifique un mtodo de devolucin de llamada que se invocar cada vez que el sistema de
propiedades determine que el valor de la propiedad ha cambiado definitivamente. Un concepto
relacionado esto ltimo es la conversin del valor de las propiedades.
Desea utilizar convenciones de metadatos establecidas que tambin se utilizan en los procesos de
WPF, como notificar si el cambio de valor de una propiedad debe exigir que el sistema de diseo
recomponga la representacin visual de un elemento. O bien, desea poder utilizar invalidaciones para
los metadatos de forma que las clases derivadas puedan modificar las caractersticas basadas en
metadatos, como el valor predeterminado.
Desea que las propiedades de un control personalizado sean compatibles con caractersticas de Visual
Studio 2008 WPF Designer, como la edicin en la ventana Propiedades.
Defina una propiedad de "contenedor" de CLR cuyo nombre coincida con el nombre de la propiedad de
dependencia. Implemente los descriptores de acceso get y set de la propiedad de "contenedor" de CLR
para conectarla con la propiedad de dependencia que la respalda.
Nota:
La implementacin tpica consiste en definir la propiedad de dependencia en el cuerpo de la clase, pero
tambin es posible definir una propiedad de dependencia en el constructor esttico de la clase. Este
enfoque podra tener sentido es necesaria ms de una lnea de cdigo para inicializar la propiedad de
dependencia.
Implementar el "contenedor"
Su implementacin del contenedor debera llamar a GetValue en la implementacin de get y a SetValue en la
implementacin de set (el campo y la llamada de registro original tambin se muestran aqu para mayor
claridad).
Salvo en circunstancias excepcionales, sus implementaciones de contenedores slo deberan realizar las
acciones GetValue y SetValue, respectivamente. El motivo de ello se explica en el tema Carga de XAML y
propiedades de dependencia.
Todas las propiedades de dependencia pblicas existentes que se incluyen en las clases de WPF utilizan este
modelo de implementacin de contenedor simple; la mayor parte de la complejidad del funcionamiento de las
propiedades de dependencia es inherentemente un comportamiento del sistema de propiedades o se
implementa a travs de otros conceptos, como la conversin o las devoluciones de llamada de cambio de
propiedad a travs de los metadatos de las propiedades.
public static readonly DependencyProperty AquariumGraphicProperty =
DependencyProperty.Register("AquariumGraphic",typeof(Uri),typeof(AquariumObject),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnUriChanged)
)
);
public Uri AquariumGraphic
{
get { return (Uri)GetValue(AquariumGraphicProperty); }
set { SetValue(AquariumGraphicProperty, value); }
}
De nuevo, por convencin, el nombre de la propiedad de contenedor debe coincidir con el nombre elegido y
usado como primer parmetro de la llamada a Register que registr la propiedad. Si su propiedad no cumple
esta convencin, no necesariamente se deshabilitan todos los usos posibles, pero encontrar varios problemas
importantes:
La implementacin actual del cargador XAML de WPF omite los contenedores por completo y se basa
en la convencin de nomenclatura a la hora de procesar los valores de los atributos.
AffectsRender indica que se ha producido algn otro cambio que no afectar al diseo ni a las
medidas, pero que requiere actualizar la representacin. Un ejemplo sera una propiedad que
cambia un color de un elemento existente, como "Background".
Estos marcadores suelen utilizarse como un protocolo en los metadatos para sus propias
implementaciones de invalidacin del sistema de propiedades o devoluciones de llamada de
diseo. Por ejemplo, puede tener una devolucin de llamada OnPropertyChanged que llame a
InvalidateArrange si alguna de las propiedades de la instancia notifica un cambio de valor y tiene
la propiedad AffectsArrange establecida en true en sus metadatos.
Algunas propiedades pueden afectar a las caractersticas de representacin del elemento primario
contenedor de forma mucho ms drstica que los cambios de tamao necesarios mencionados
anteriormente. Un ejemplo es la propiedad MinOrphanLines que se utiliza en el modelo de documentos
dinmicos, cuyos cambios pueden afectar a la representacin global del documento dinmico que
contiene el prrafo. Utilice AffectsParentArrange o AffectsParentMeasure para identificar casos
similares en sus propias propiedades.
De forma predeterminada, el Modo de enlace de datos para las propiedades de dependencia toma
como valor predeterminado OneWay. Siempre puede cambiar el enlace para que sea TwoWay por cada
instancia de enlace. Pero como autor de la propiedad de dependencia, puede hacer la que propiedad
utilice el modo de enlace TwoWay de forma predeterminada. Un ejemplo de una propiedad de
dependencia existente es MenuItem.IsSubmenuOpen; el escenario para esta propiedad es que la
lgica de establecimiento de IsSubmenuOpen y la composicin de MenuItem interacten con el estilo
del tema predeterminado. La lgica de la propiedad IsSubmenuOpen utiliza el enlace de datos de
forma nativa para mantener el estado de la propiedad de acuerdo con otras propiedades de estado y
llamadas a mtodos. Otra propiedad de ejemplo que enlaza TwoWay de forma predeterminada es
TextBox.Text.
Establezca el marcador Journal para indicar si los servicios d el diario de navegacin deben detectar o
utilizar su propiedad. Un ejemplo es la propiedad SelectedIndex; todos los elementos seleccionados en
un control de seleccin deben mantenerse cuando se navega por el historial del diario.
Valor predeterminado para la propiedad de dependencia, si no se puede determinar ningn otro valor
para la propiedad de dependencia por valor local, estilo, herencia, etc. Para ver una explicacin en
profundidad de cmo los valores predeterminados participan en la prioridad utilizada por el sistema de
propiedades al asignar valores para las propiedades de dependencia.
Si la propiedad de dependencia en cuestin se considera una propiedad del nivel de marco de trabajo
de WPF, los metadatos pueden contener caractersticas de propiedad del nivel de marco de trabajo de
WPF, que proporcionan informacin e indican el estado de servicios tales como el motor de diseo del
nivel de marco de trabajo de WPF y la lgica de herencia de propiedad.
API de metadatos
El tipo que informa de la mayor parte de la informacin de los metadatos utilizados por el sistema de propiedad
es la clase PropertyMetadata. Las instancias de metadatos se especifican opcionalmente cuando se registran
propiedades de dependencia con el sistema de propiedades y pueden especificarse de nuevo para tipos
adicionales que se agregan a s mismos como propietarios o invalidan los metadatos que heredan de la
definicin de propiedad de dependencia de la clase base. (Para los casos donde un registro de propiedad no
especifica metadatos, se crea un objeto PropertyMetadata predeterminado con valores predeterminados para
esa clase.) Los metadatos registrados se devuelven como PropertyMetadata al llamar a las diversas
sobrecargas de GetMetadata que obtienen metadatos de una propiedad de dependencia de una instancia de
DependencyObject.
Entonces se deriva la clase PropertyMetadata para proporcionar metadatos ms concretos para divisiones
arquitectnicas tales como las clases de nivel de marco de trabajo de WPF. UIPropertyMetadata agrega informe
de animacin y [ T:System.Windows.FrameworkPropertyMetadata] proporciona las propiedades de nivel de
marco de trabajo de WPF mencionadas en la seccin anterior. Cuando se registra propiedades de dependencia,
se puede registrarlas con estas clases derivadas de PropertyMetadata. Cuando se examina los metadatos, el
tipo PropertyMetadata base se puede convertir en las clases derivadas para poder examinar las propiedades
ms concretas.
Nota:
Las caractersticas de propiedad que se pueden especificar en FrameworkPropertyMetadata se citan a veces
en esta documentacin como "marcadores". Al crear nuevas instancias de metadatos para su uso en
registros de propiedad de dependencia o invalidaciones de metadatos, debe especificar estos valores
mediante la enumeracin basada en marcadores FrameworkPropertyMetadataOptions y, a continuacin,
proporcionar
valores
de
la
enumeracin
posiblemente
concatenados
al
constructor
FrameworkPropertyMetadata. Sin embargo, una vez construidas, estas caractersticas de opcin se exponen
dentro de un objeto FrameworkPropertyMetadata como una serie de propiedades booleanas en lugar del
valor de enumeracin de construccin. Las propiedades booleanas permiten comprobar cada condicional, en
lugar de exigir que se aplique una mscara a un valor de enumeracin basado en marcadores para obtener
la informacin de inters. El constructor utiliza la enumeracin FrameworkPropertyMetadataOptions
concatenada para mantener la longitud de la firma del constructor dentro de lo razonable, mientras que los
metadatos construidos reales exponen las propiedades discretas para hacer que la consulta de los
metadatos sea ms intuitiva.
Cundo invalidar metadatos, cundo derivar una clase
El sistema de propiedades de WPF ha establecido funciones para modificar algunas caractersticas de las
propiedades de dependencia sin necesidad de implementarlas de nuevo por completo. Esto se logra
construyendo una instancia diferente de los metadatos de propiedad para la propiedad de dependencia tal como
existe en un tipo determinado. Tenga en cuenta que la mayora de las propiedades de dependencia existentes
no son propiedades virtuales as que, en rigor, la "reimplantacin" de clases heredadas solamente podra
lograrse sombreando el miembro existente.
Si el escenario que est intentando habilitar para una propiedad de dependencia en un tipo no se puede lograr
modificando caractersticas de propiedades de dependencia existentes, puede que sea necesario crear una clase
derivada y, a continuacin, declarar una propiedad de dependencia personalizada en la clase derivada. Una
propiedad de dependencia personalizada se comporta de forma idntica a las propiedades de dependencia
definidas por las API de WPF.
Una caracterstica notable de una propiedad de dependencia que no se puede invalidar es su tipo de valor. Si
est heredando una propiedad de dependencia que tiene el comportamiento aproximado que necesita, pero
necesita que tenga un tipo diferente, tendr que implementar una propiedad de dependencia personalizada y,
quiz, vincular las propiedades mediante conversin de tipos u otra implementacin en la clase personalizada.
Adems, no es posible invalidar un objeto ValidateValueCallbackexistente, porque esta devolucin de llamada
existe en el propio campo de registro y no dentro de sus metadatos.
Escenarios para modificar metadatos existentes
Si est trabajando con metadatos de una propiedad de dependencia existente, un escenario comn para
modificar metadatos de propiedades de dependencia consiste en modificar el valor predeterminado. Cambiar o
agregar devoluciones de llamada del sistema de propiedades es un escenario ms avanzado. Quiz desee
hacerlo si la implementacin de una clase derivada tiene diferentes interrelaciones entre propiedades de
dependencia. Uno de los condicionantes de tener un modelo de programacin que admita tanto cdigo como el
uso declarativo es que las propiedades deben poder establecerse en cualquier orden. En consecuencia, las
propiedades dependientes deben establecerse en el momento, sin contexto, y no pueden apoyarse en el
conocimiento de un orden de configuracin, tal como el que podra encontrarse en un constructor. Observe que
las devoluciones de llamada de la validacin no forman parte de los metadatos; forman parte del identificador
de propiedad de dependencia. Por consiguiente, las devoluciones de llamada de validacin no se pueden
modificar reemplazando metadatos.
En algunos casos, quiz desee tambin modificar las opciones de metadatos de propiedad del nivel de marco de
trabajo de WPF en propiedades de dependencia existentes. Estas opciones comunican ciertos condicionales
conocidos sobre propiedades del nivel de marco de trabajo de WPF a otros procesos del nivel de marco de
trabajo de WPF tales como el sistema de diseo. La configuracin de opciones, en general, solamente se hace
cuando se registra una nueva propiedad de dependencia, pero tambin es posible cambiar los metadatos de la
propiedad de nivel de marco de trabajo de WPF como parte de una llamada a OverrideMetadata o a AddOwner.
Invalidar metadatos
El propsito de invalidar metadatos es, principalmente, ofrecer la oportunidad de modificar los diversos
comportamientos derivados de metadatos que se aplican a la propiedad de dependencia tal como existe en el
tipo. Las razones para ello se explican con ms detalle en la seccin Metadatos.
Los metadatos de propiedad se pueden proporcionar para una propiedad de dependencia durante la llamada de
registro (Register). Sin embargo, en muchos casos, quiz desee proporcionar metadatos especficos del tipo
para
la
clase
cuando
herede
esa
propiedad
de
dependencia.
Puede
hacerlo
llamando
al
mtodo
Se
reemplazan
las
implementaciones
de
CoerceValueCallback.
Si
agrega
una
nueva
los
metadatos
inmediatos. Se
retiene
implementaciones
de
CoerceValueCallback en la jerarqua.
Este comportamiento se implementa mediante Merge y se puede invalidar en las clases de metadatos derivadas
Invalidar metadatos de propiedades asociadas
En WPF, las propiedades asociadas se implementan como propiedades de dependencia. Esto significa que
tambin tienen metadatos de propiedad, que las clases individuales pueden invalidar. Las consideraciones de
mbito para una propiedad asociada en WPF son generalmente que cualquier objeto DependencyObject puede
tener una propiedad asociada establecida. Por consiguiente, cualquier clase derivada de DependencyObject
puede invalidar los metadatos de cualquier propiedad asociada, pues podran establecerse en una instancia de
la clase. Puede invalidar valores predeterminados, devoluciones de llamada o propiedades de informe de
caractersticas de nivel de marco de trabajo de WPF. Si la propiedad asociada se establece en una instancia de
la clase, se aplicarn las caractersticas de los metadatos de la propiedad de reemplazo. Por ejemplo, puede
invalidar el valor predeterminado, de modo que se informe del valor de invalidacin como valor de la propiedad
asociada en las instancias de la clase, siempre que la propiedad no se establezca de otra manera.
Nota:
La propiedad Inherits no es relevante para propiedades asociadas.
Agregar una clase como propietaria de una propiedad de dependencia existente
Una clase se puede agregar a s misma como propietaria de una propiedad de dependencia que ya se haya
registrado, utilizando el mtodo AddOwner. Esto permite que la clase utilice una propiedad de dependencia
registrada originalmente para un tipo diferente. La clase que se agrega no es, normalmente, una clase derivada
del tipo que registr como propietario esa propiedad en primer lugar. En la prctica, esto permite que la clase y
sus clases derivadas "hereden" una implementacin de la propiedad de dependencia sin que la clase propietaria
original y la clase que se agrega estn en la misma jerarqua de clases real. Adems, la clase que se agrega (y
AffectsParentMeasure).
Algunos
ejemplos
en
que
se
establecen
estos
Inherits. De
propiedades de dependencia no
heredan valores.
OverridesInheritanceBehavior permite que la ruta de herencia tambin recorra un rbol visual, lo que
es necesario para algunos escenarios de composicin de controles.
Nota:
El trmino "heredar" en el contexto de los valores de propiedad tiene un significado concreto para
las propiedades de dependencia: significa que los elementos secundarios pueden heredar el valor
de la propiedad de dependencia real de los elementos primarios gracias a una funcin de nivel de
marco de trabajo de WPF del sistemas de propiedades de WPF. No tiene nada que ver directamente
con la herencia de miembros y tipos de cdigo administrado a travs de tipos derivados.
Comunicacin de si las aplicaciones o los servicios compatibles con el diario deben incluir en l las
propiedades (Journal). Para los elementos generales, la inclusin en el diario no est habilitada de
manera predeterminada, sino que se habilita de manera selectiva para algunos controles de datos
proporcionados por el usuario. Esta propiedad sirve para que la lean los servicios de diario, incluida la
implementacin del diario de WPF, y suele establecerse para controles de usuario tales como
selecciones del usuario en listas que deben conservarse en los pasos de navegacin subsiguientes.
Leer FrameworkPropertyMetadata
Cada
una
de
las
propiedades
vinculadas
anteriormente
son
propiedades
especficas
que
Utilice una de las firmas sin un parmetro flags y, a continuacin, establezca la propiedad Boolean de
comunicacin de FrameworkPropertyMetadata en true para cada cambio de caracterstica deseado. Si lo
hace, debe establecer estas propiedades antes de construir cualquier elemento con esta propiedad de
dependencia; las propiedades Boolean son de lectura y escritura a fin de permitir este comportamiento
consistente en evitar el parmetro flags y, an as, rellenar los metadatos, pero los metadatos deben
quedar sellados de manera efectiva antes de utilizar la propiedad. As pues, si intenta establecer las
propiedades despus de solicitar los metadatos, la operacin no ser vlida.
Comportamiento de combinacin de metadatos de propiedades de marco de trabajo
Cuando se invalidan los metadatos de propiedades de marco de trabajo, las distintas caractersticas de los
metadatos se combinan o reemplazan.
Se
reemplazan
las
implementaciones
de
CoerceValueCallback.
Si
agrega
una
nueva
los
metadatos
inmediatos. Se
retiene
implementaciones
de
CoerceValueCallback en la jerarqua.
de
utilizar
los
diversos
valores
de
las
propiedad
Boolean
equivalentes
de
3.
4.
2.
5.
Estilo implcito. Slo se aplica a la propiedad Style. La propiedad Style se llena con cualquier recurso
de estilo cuya clave coincida con el tipo de ese elemento. Ese recurso de estilo debe existir o en la pgina
o en la aplicacin; la bsqueda de un recurso de estilo implcito no contina en los temas.
implcitos, pero
no proceder de
los estilos
8.
9.
Estilo predeterminado (tema). Para obtener informacin ms detallada sobre cundo se aplica y cmo
se relacionan los estilos del tema con las plantillas incluidas en los estilos del tema. Dentro de un estilo
predeterminado se aplica el orden de prioridad siguiente:
10.
1.
2.
Herencia. Algunas propiedades de dependencia heredan sus valores del elemento primario a los
elementos secundarios, de forma que es necesario establecerlas especficamente en cada elemento de la
aplicacin.
11.
TemplatedParent
TemplatedParent no se aplica como un elemento de prioridad a cualquier propiedad de un elemento que se
declara directamente en el marcado de la aplicacin estndar. El concepto de TemplatedParent slo existe para
los elementos secundarios dentro de un rbol visual que se generan al aplicar la plantilla. Cuando el sistema de
propiedades busca un valor en la plantilla TemplatedParent, est buscando en la plantilla que cre ese
elemento. Los valores de propiedades procedentes de la plantilla TemplatedParent generalmente se comportan
como si se hubieran establecido como un valor local en el elemento secundario, pero esta prioridad menor
frente a la del valor local existe porque es posible que las plantillas se compartan.
La propiedad Style.
El orden de bsqueda descrito anteriormente se aplica a todas las propiedades de dependencia posibles excepto
una: la propiedad Style. La propiedad Style es nica porque no se le pueden aplicar estilos, por lo que no le
aplican los elementos de prioridad del 5 al 8. Asimismo, no se recomienda animar o convertir Style (animar
Style requerira una clase de animacin personalizada). De este modo, quedan tres formas en las que se podra
establecer la propiedad Style:
Estilo implcito. El valor de la propiedad Style no se establece directamente. Sin embargo, Style existe
en algn nivel en la secuencia de bsqueda de recursos (pgina, aplicacin) y se le asigna una clave
Estilo predeterminado, tambin conocido como el estilo del tema. La propiedad Style no se establece
directamente y de hecho se leer como null hasta el tiempo de ejecucin. En este caso, el estilo
procede de la evaluacin del tema en tiempo de ejecucin que forma parte del motor de presentacin
de WPF.
Para los estilos implcitos que no pertenecen a los temas, el tipo debe coincidir exactamente: una clase
derivada de MyButtonButton no utilizar implcitamente un estilo para Button.
Estilos predeterminados (tema)
Cada control que se distribuye con WPF tiene un estilo predeterminado. Ese estilo predeterminado puede variar
para cada tema, motivo por el que a veces se le conoce como estilo del tema.
La informacin ms importante que se incluye en un estilo predeterminado para un control es su plantilla de
control, que existe en el estilo del tema como un establecedor para su propiedad Template. Si no hubiera
ninguna plantilla en los estilos predeterminados, un control sin una plantilla personalizada como parte de un
estilo personalizado no tendra ninguna apariencia visual. La plantilla del estilo predeterminado da una
estructura bsica a la apariencia visual de cada control y tambin define las conexiones entre las propiedades
definidas en el rbol visual de la plantilla y la clase de control correspondiente. Cada control expone un
conjunto de propiedades que pueden influir en la apariencia visual del control sin reemplazar la plantilla por
completo. Por ejemplo, considere la apariencia visual predeterminada de un control Thumb, que es un
componente de ScrollBar.
Un control Thumb tiene ciertas propiedades personalizables. La plantilla predeterminada de un control Thumb
crea una estructura bsica o rbol visual con varios componentes Border anidados para crear una apariencia de
tipo bisel. Si se va a exponer una propiedad que forma parte de la plantilla para que la personalice la clase
Thumb, dicha propiedad debe ser expuesta mediante TemplateBinding dentro de la plantilla. En el caso de
Thumb, varias propiedades de estos bordes comparten un enlace de plantilla a propiedades como Background o
BorderThickness. Pero algunas otras propiedades u organizaciones visuales estn incluidas en el cdigo de la
plantilla de control o se enlazan a valores que proceden directamente del tema y no se pueden cambiar salvo
reemplazando la plantilla completa. Generalmente, si una propiedad procede de un elemento primario con
plantilla y no se expone mediante un enlace de plantilla, no puede ajustarse mediante los estilos, porque no
hay ninguna manera sencilla de especificarla como destino. Pero la herencia de valores de propiedades de la
plantilla aplicada todava podra influir en esa propiedad, igual que podra hacerlo el valor predeterminado.
Los estilos del tema utilizan un tipo como clave en sus definiciones. Sin embargo, cuando se aplican temas a
una instancia determinada de un elemento, la bsqueda de los temas para este tipo se realiza comprobando la
propiedad DefaultStyleKey en un control. Esto contrasta con el uso del tipo literal, tal como hacen los estilos
implcitos. El valor de DefaultStyleKey se heredara a las clases derivadas incluso si el implementador no lo
cambiara (la forma prevista de cambiar la propiedad no es invalidarla en el nivel de propiedad, sino cambiar su
valor predeterminado en los metadatos de la propiedad). Este direccionamiento indirecto permite a las clases
base definir los estilos del tema para los elementos derivados que, de otra forma, no tendran ningn estilo (o,
lo que es ms importante, no tienen una plantilla dentro de ese estilo y, por ello, no tendran ningn tipo de
apariencia visual predeterminada). As, puede derivar MyButton de Button y aun as obtener la plantilla
predeterminada de Button. Si fuera el autor del control MyButton y deseara un comportamiento diferente,
podra invalidar los metadatos de la propiedad de dependencia para DefaultStyleKey en MyButton con objeto de
devolver una clave diferente y, a continuacin, definira los estilos del tema pertinentes, incluyendo la plantilla
para MyButton que debe empaquetar con su control MyButton.
Por supuesto, el valor o campo privado que respalda la propiedad de dependencia de slo lectura puede ser de
lectura y escritura con la lgica que usted decida. Sin embargo, la manera ms sencilla de establecer la
propiedad, ya sea inicialmente o como parte de lgica de tiempo de ejecucin, es utilizar las API del sistema de
propiedades, en lugar de eludir el sistema de propiedades y establecer directamente el campo de respaldo
privado. En particular, existe una firma de SetValue que acepta un parmetro de tipo DependencyPropertyKey.
Cmo y dnde se establezca este valor mediante programacin dentro de la lgica de la aplicacin afectar a
cmo se establecer el acceso en la DependencyPropertyKey creada al registrar la propiedad de dependencia
por primera vez. Si toda esta lgica se administra dentro de la clase, puede hacerlo privado, pero si requiere
que se establezca desde otro componente del ensamblado, puede establecerlo como interno. Un enfoque
consiste en llamar a SetValue dentro de un controlador de eventos de clase de un evento pertinente que
comunique a una instancia de clase que es preciso cambiar el valor almacenado de la propiedad. Otro enfoque
consiste
en
vincular
las
propiedades
de
dependencia
entre
mediante
devoluciones
de
llamada
describe
en
Cmo:
Registrar
una
propiedad
asociada.
Registre
la
propiedad
con
metadatos
Aunque puede que parezca que la herencia de valores de propiedad funciona para las propiedades de
dependencia no asociadas, no se ha definido el comportamiento de la herencia de una propiedad no
asociada a travs de algunos lmites de elementos del rbol en tiempo de ejecucin. Utilice siempre
RegisterAttached para registrar las propiedades en las que especifique Inherits en los metadatos.
Heredar valores de propiedad a travs de los lmites del rbol
La herencia de propiedades funciona atravesando un rbol de elementos. Este rbol suele ser paralelo al rbol
lgico. Sin embargo, cada vez que se incluye un objeto de nivel bsico de WPF en el marcado que define un
rbol de elementos, como un Brush, se crea un rbol lgico discontinuo. Un verdadero rbol lgico no se
extiende conceptualmente a travs de Brush, porque el rbol lgico es un concepto de nivel de marco de
trabajo de WPF. Puede observar esta situacin reflejada en los resultados cuando utilice los mtodos de
LogicalTreeHelper. Sin embargo, la herencia de valores de propiedad puede cerrar esta brecha del rbol lgico y
pasar a travs de ella los valores heredados, siempre que la propiedad heredable se haya registrado como
propiedad asociada y no se encuentre ningn lmite de bloqueo deliberado de la herencia (como un control
Frame).
contenedor
de
propiedad
CLR,
donde
esa
propiedad
est
respaldada
por
un
identificador
de
DependencyProperty, en lugar de por un campo u otra construccin. Este mismo modelo se sigue al
implementar una propiedad de tipo de coleccin. Sin embargo, una propiedad de tipo de coleccin presenta
cierta complejidad en el modelo cada vez el tipo contenido en la coleccin es, a su vez, una clase derivada de
DependencyObject o Freezable.
Inicializar la coleccin ms all del valor predeterminado
Al crear una propiedad de dependencia, no se especifica el valor predeterminado de la misma como el valor
inicial del campo. En su lugar, se especifica el valor predeterminado a travs de los metadatos de la propiedad
de dependencia. Si la propiedad es un tipo de referencia, el valor predeterminado especificado en sus
metadatos no es un valor predeterminado de una instancia individual, sino un valor predeterminado que se
aplica a todas las instancias del tipo. Por consiguiente, debe extremar las precauciones para no utilizar la
coleccin esttica singular definida por los metadatos de la propiedad de coleccin como el valor
predeterminado activo de las instancias recin creadas de su tipo. En vez de eso, debe asegurarse de
establecer de manera deliberada el valor de coleccin en una coleccin nica (instancia) como parte de la lgica
del constructor de clase. De lo contrario, habr creado involuntariamente una clase singleton.
Considere el ejemplo siguiente. En la seccin siguiente del ejemplo se muestra la definicin de una clase
Aquarium. La clase define la propiedad de dependencia de tipo de coleccin AquariumObjects, que utiliza el tipo
List<(Of <(T>)>) genrico con una restriccin de tipo FrameworkElement. En la llamada a Register(String,
Type, Type, PropertyMetadata) para la propiedad de dependencia, los metadatos establecen el valor
predeterminado en un nuevo objeto List<(Of <(T>)>) genrico.
public class Fish : FrameworkElement { }
public class Aquarium : DependencyObject
{
private static readonly DependencyPropertyKey AquariumContentsPropertyKey =
DependencyProperty.RegisterReadOnly(
...
}
Sin embargo, si se limita a dejar el cdigo tal y como se muestra, ese valor predeterminado nico de la lista se
compartir para todas las instancias de Aquarium. Si ejecutara el cdigo de pruebas siguiente, diseado para
mostrar cmo crear dos instancias independientes de Aquarium y agregar un tipo Fish nico diferente a cada
una de ellas, vera un resultado sorprendente:
Aquarium myAq1 = new Aquarium();
Aquarium myAq2 = new Aquarium();
Fish f1 = new Fish();
Fish f2 = new Fish();
myAq1.AquariumContents.Add(f1);
myAq2.AquariumContents.Add(f2);
MessageBox.Show("aq1 contains " + myAq1.AquariumContents.Count.ToString() + " things");
MessageBox.Show("aq2 contains " + myAq2.AquariumContents.Count.ToString() + " things");
En lugar de que el recuento de cada coleccin sea de uno, el recuento de cada coleccin es de dos! Esto se
debe a que cada Aquarium agreg Fish a la coleccin de valores predeterminados, resultante de una llamada de
constructor nica en los metadatos, con lo que se comparte entre todas las instancias. Esta situacin casi nunca
es deseable.
Para corregir este problema, debe restablecer el valor de la propiedad de dependencia de coleccin en una
instancia nica, como parte de la llamada al constructor de clase. Dado que la propiedad es de dependencia y
de slo lectura, se utiliza el mtodo SetValue(DependencyPropertyKey, Object) para establecerla, utilizando una
clave DependencyPropertyKey que slo est accesible dentro de la clase.
public Aquarium() : base()
{
SetValue(AquariumContentsPropertyKey, new List<FrameworkElement>());
}
Ahora, si ejecuta de nuevo el mismo cdigo de pruebas de antes, los resultados seran ms previsibles, ya que
Aquarium tiene su propia coleccin nica.
Habra una ligera variacin en el modelo si optase por hacer la propiedad de coleccin de lectura y escritura. En
ese caso, podra llamar al descriptor de acceso set pblico desde el constructor para llevar a cabo la
inicializacin, en la que igualmente se llamara a la firma sin clave de SetValue(DependencyProperty, Object)
dentro del contenedor set, utilizando un identificador de DependencyProperty pblico.
Comunicar los cambios de valores de enlace de propiedades de coleccin
Una propiedad de coleccin que tambin es de dependencia no comunica automticamente los cambios a sus
subpropiedades. Si crea enlaces en una coleccin, esto puede evitar que el enlace comunique los cambios, lo
que invalida algunos escenarios de enlace de datos. Sin embargo, si utiliza el tipo de coleccin
FreezableCollection<(Of <(T>)>), entonces s se comunican correctamente los cambios de las subpropiedades
a los elementos contenidos en la coleccin y el enlace funciona como est previsto.
Para habilitar el enlace de subpropiedades en una coleccin de objetos de dependencia, cree la propiedad de
coleccin como el tipo FreezableCollection<(Of <(T>)>), con una restriccin de tipo para esa coleccin a
cualquier clase derivada de DependencyObject.
3.6. Eventos
Windows Presentation Foundation (WPF) introduce eventos enrutados que pueden invocar controladores que
existen en varios agentes de escucha en el rbol de elementos de una aplicacin.
En este rbol de elementos simplificado, el origen de un evento Click es uno de los elementos Button y el
elemento Button en el que se hizo clic es el primer elemento que tiene la oportunidad de controlar el evento.
Pero si ninguno de los controladores asociados a Button acta sobre el evento, este se propagar hacia arriba
hasta el elemento primario de Button en el rbol de elementos, que es StackPanel. Potencialmente, el evento
se propaga hasta Border y, a continuacin, contina hacia la raz de la pgina en el rbol de elementos (que no
se muestra).
En otras palabras, la ruta de eventos para este evento Click es:
Botn-->StackPanel-->Borde-->...
Directo: slo el propio elemento de origen tiene la oportunidad de invocar controladores como
respuesta. Esto es anlogo al "enrutamiento" utilizado por formularios Windows Forms para los
eventos. Sin embargo, a diferencia de un evento CLR estndar, los eventos con enrutamiento directo
admiten el control de clases (el control de clases se explica en una seccin posterior) y pueden ser
utilizados por EventSetter y EventTrigger.
Algunas caractersticas del diseo de estilos y plantillas de WPF, como EventSetter y EventTrigger
requieren que el evento al que se hace referencia sea un evento enrutado. Este es el escenario del
identificador de eventos mencionado anteriormente.
Los eventos enrutados admiten un mecanismo de control de clases en el que la clase puede especificar
mtodos estticos que tienen la oportunidad de controlar eventos enrutados antes de que cualquier
controlador de instancias registrado tenga acceso a ellos. Esto es muy til en el diseo de controles,
porque una clase puede exigir comportamientos de clase orientados a eventos que no se pueden
suprimir accidentalmente controlando un evento en una instancia.
Cada una de las consideraciones anteriores se explica en una seccin independiente de este tema.
Agregar e implementar un controlador de eventos para un evento enrutado
Para agregar un controlador de eventos en XAML, basta con que agregue el nombre del evento a un elemento
como un atributo y establezca el valor del atributo en el nombre del controlador de eventos que implementa un
delegado adecuado, como en el ejemplo siguiente.
<Button Click="b1SetColor">button</Button>
b1SetColor es el nombre del controlador implementado que contiene el cdigo que controla el evento Click.
b1SetColor debe tener la misma firma que el delegado RoutedEventHandler, que es el delegado del controlador
de eventos para el evento Click. El primer parmetro de todos los delegados del controlador de eventos
enrutado especifica el elemento al que se agrega el controlador de eventos y el segundo parmetro especifica
los datos para el evento.
void b1SetColor(object sender, RoutedEventArgs args)
{
//logic to handle the Click event
...
}
RoutedEventHandler es el delegado del controlador de eventos enrutados bsico. Para los eventos enrutados
especializados para ciertos controles o escenarios, los delegados que deben usarse para los controladores de
eventos enrutados tambin podran volverse ms especializados, de forma que puedan transmitir datos de
evento especializados. Por ejemplo, en un escenario de entrada comn, podra controlar un evento enrutado
DragEnter. Su controlador debera implementar el delegado DragEventHandler. Utilizando el delegado ms
concreto, puede procesar DragEventArgs en el controlador y leer la propiedad Data, que contiene la carga del
portapapeles de la operacin de arrastrar.
Resulta sencillo agregar un controlador para un evento enrutado en una aplicacin que se crea mediante
cdigo. Los controladores de eventos enrutados siempre se pueden agregar a travs de un mtodo auxiliar
AddHandler (que es el mismo mtodo al que llama el respaldo existente para add). Sin embargo, los eventos
enrutados de WPF existentes generalmente tienen implementaciones de respaldo de lgica add y remove que
permiten agregar controladores para los eventos enrutados mediante una sintaxis de eventos especfica del
lenguaje, que una sintaxis ms intuitiva que el mtodo de aplicacin auxiliar. A continuacin se muestra un
ejemplo de uso del mtodo auxiliar:
En cdigo, en lugar de utilizar una sintaxis de eventos especfica del lenguaje que funciona para los
eventos CLR generales, llame al mtodo AddHandler(RoutedEvent, Delegate, Boolean) de WPF para
agregar su controlador. Especifique el valor de handledEventsToo como true.
Aparte del comportamiento que genera el estado Handled en los eventos enrutados, el concepto de Handled
tiene implicaciones para el modo en que se disea una aplicacin y se escribe el cdigo del controlador de
eventos. Puede conceptuar Handled como un protocolo simple que exponen los eventos enrutados. La forma
concreta en que utilice este protocolo depende de usted, pero el diseo conceptual de cmo se debe utilizar el
valor de Handled es el siguiente:
Si un evento enrutado est marcado como controlado, no es necesario que los dems elementos a lo
largo de esa ruta lo controlen de nuevo.
Si un evento enrutado no est marcado como controlado, significa que los dems agentes de escucha
situados anteriormente a lo largo de la ruta han decidido no registrar un controlador o que los
controladores que se registraron decidieron no manipular los datos de evento y establecer Handled en
true. Tambin es posible que el agente de escucha actual sea el primer punto de la ruta. Llegados a
este punto, los controladores del agente de escucha actual tienen tres posibles lneas de accin:
No realizar ninguna accin; el evento sigue estando sin controlar y se enruta al agente de
escucha siguiente.
Ejecutar cdigo en respuesta al evento. Marcar el evento como controlado en los datos de
evento pasados al controlador, porque la accin realizada se considera lo suficientemente
sustancial como para marcarlo como controlado. El evento se enruta al agente de escucha
siguiente, pero con Handled=true en sus datos de evento, de forma que slo los agentes de
escucha handledEventsToo tengan la oportunidad de invocar ms controladores.
2.
3.
4.
5.
6.
Un delegado de controlador de eventos enrutados proporciona referencias a dos objetos: el objeto que
desencaden el evento y el objeto en el que se invoc el controlador. El objeto en el que se invoc el
controlador es el objeto sobre el que informa el parmetro sender. La propiedad Source de los datos del evento
informa sobre el objeto en el que se desencaden el evento por primera vez. Un evento enrutado tambin
puede desencadenarlo y controlarlo el mismo objeto, en cuyo caso sender y Source son idnticos (esto es lo
que ocurre con los pasos 3 y 4 de la lista del ejemplo de procesamiento de eventos).
Debido a los mecanismos de tnel y de propagacin, los elementos principales reciben eventos de entrada en
los que Source es uno de sus elementos secundarios. Cuando es importante para conocer cul es el elemento
de origen, puede identificarlo teniendo acceso a la propiedad Source.
Normalmente, una vez que el evento de entrada se marca como Handled, ya no se invocan ms controladores.
Lo habitual es marcar los eventos de entrada como controlados en cuanto se invoca un controlador que se
ocupa del control lgico especfico de la aplicacin relacionado con el significado del evento de entrada.
La excepcin a estas directrices generales sobre el estado Handled es que los controladores del evento de
entrada que se registran para omitir deliberadamente el estado Handled de los datos de evento todava se
invocaran a lo largo de cualquiera de las rutas.
El modelo de datos de evento compartido entre los eventos de tnel y de propagacin, y el desencadenamiento
en primer lugar de los eventos de tnel y a continuacin de los de propagacin no es un concepto que se
cumpla
de
forma
general
para
todos
los
eventos
enrutados.
Ese
comportamiento
se
implementa
especficamente segn el modo en que los dispositivos de entrada de WPF deciden desencadenar y conectar los
pares de eventos de entrada. Implementar sus propios eventos de entrada es un escenario avanzado, pero
tambin podra decidir seguir ese modelo para sus propios eventos de entrada.
Ciertas clases eligen controlar ciertos eventos de entrada mediante clases, normalmente con la intencin de
volver a definir lo que significa un determinado evento de entrada controlado por el usuario dentro de ese
control y de desencadenar un nuevo evento.
EventSetters y EventTriggers
Un mtodo Add*Handler con dos parmetros. El primer parmetro debe identificar el evento y el
evento identificado debe coincidir con nombres que tengan * en el nombre de mtodo. El segundo
parmetro es el controlador que se va a agregar. El mtodo debe ser pblico y esttico, sin ningn
valor devuelto.
Un mtodo Remove*Handler con dos parmetros. El primer parmetro debe identificar el evento y el
evento identificado debe coincidir con nombres que tengan * en el nombre de mtodo. El segundo
parmetro es el controlador que se va a quitar. El mtodo debe ser pblico y esttico, sin ningn valor
devuelto.
El mtodo de descriptor de acceso Add*Handler facilita el procesamiento XAML cuando se declaran atributos de
controlador de eventos asociados en un elemento. Los mtodos Add*Handler y Remove*Handler tambin
permiten el acceso mediante cdigo al almacn de controladores de eventos del evento asociado.
Este modelo general no es lo bastante preciso para la implementacin prctica en un marco de trabajo, porque
cada implementacin de lector de XAML podra tener esquemas diferentes para identificar los eventos
subyacentes en el lenguaje y la arquitectura de respaldo. sta es una de las razones por las que WPF
implementa los eventos asociados como eventos enrutados; el identificador que debe utilizarse para un evento
(RoutedEvent) ya est definido por el sistema de eventos de WPF. Asimismo, enrutar un evento constituye una
extensin natural de la implementacin en el concepto de nivel de lenguaje de XAML de un evento asociado.
La implementacin de Add*Handler para un evento asociado de WPF est compuesto de una llamada a
AddHandler con el evento enrutado y el controlador como argumentos.
En general, esta estrategia de implementacin y el sistema de eventos enrutados restringen el control de los
eventos asociados a las clases derivadas de UIElement o de ContentElement, porque slo ellas tienen
implementaciones de AddHandler.
Por ejemplo, en el cdigo siguiente se define el evento asociado NeedsCleaning de la clase propietaria
Aquarium; para ello se utiliza la estrategia de eventos asociados de WPF consistente en declarar el evento
asociado como evento enrutado.
<aqua:Aquarium Name="theAquarium" Height="600" Width="800"
aqua:AquariumFilter.NeedsCleaning="WashMe"/>
Observe que el mtodo utilizado para establecer el campo de identificador
del
evento
asociado,
RegisterRoutedEvent, es en realidad el mismo mtodo que se utiliza para registrar un evento enrutado no
asociado. Tanto los eventos asociados como los eventos enrutados se registran en un almacn interno
centralizado. Esta implementacin de almacn de eventos permite la consideracin conceptual de Uso de
eventos como interfaces.
Provocar un evento asociado de WPF
Normalmente, no es necesario provocar los eventos asociados existentes definidos en WPF mediante cdigo.
Estos eventos siguen el modelo conceptual general de "servicio", donde las responsables de provocar los
eventos son las clases de servicio, como InputManager.
Sin embargo, si define un evento asociado personalizado basado en el modelo de WPF consistente en basar los
eventos asociados en eventos enrutados (RoutedEvent), puede utilizar RaiseEvent para provocar un evento
asociado de cualquier objeto UIElement o ContentElement. Para provocar un evento enrutado (asociado o no)
es preciso declarar un elemento concreto del rbol de elementos como origen del evento; este origen se
comunica como llamador del mtodo RaiseEvent. Determinar qu elemento se comunica como origen en el
rbol es responsabilidad del servicio.
Las clases derivadas pueden complementar el control de clases heredado de la clase base agregando
un controlador que no marca el evento enrutado como controlado, porque el controlador de la clase
base se invocar despus que el controlador de la clase derivada.
Las clases derivadas pueden reemplazar el control de clases de la clase base agregando un controlador
de clases que marca el evento enrutado como controlado. Debera tener cuidado con este enfoque,
porque es posible que cambie el diseo del control de base deseado en reas como el aspecto visual,
la lgica de estados, el control de entrada y el control de comandos.
Control de clases de los eventos enrutados por las clases base de los controles
En el nodo de cada uno de los elementos de una ruta de eventos, los agentes de escucha de la clase tienen la
oportunidad de responder al evento enrutado antes de que lo haga cualquier agente de escucha de la instancia
del elemento. Por esta razn, a veces se utilizan los controladores de clases para suprimir eventos enrutados
que una implementacin de una clase de control determinada no desea que se propaguen ms, o para
proporcionar un control especial de ese evento enrutado que es una caracterstica de la clase. Por ejemplo, una
clase podra desencadenar su propio evento especfico de la clase que contiene caractersticas ms concretas
sobre el significado de alguna condicin de los datos proporcionados por el usuario en el contexto de esa clase
en particular. La implementacin de la clase podra marcar el evento enrutado ms general como controlado.
Los controladores de clases normalmente se agregan de forma que no se invoquen para los eventos enrutados
cuyos datos de evento compartidos ya se han marcado como controlados, pero para casos atpicos tambin hay
una firma RegisterClassHandler(Type, RoutedEvent, Delegate, Boolean) que registra los controladores de clases
para que tambin se invoquen cuando los eventos enrutados se marquen como controlados.
Elementos virtuales de controlador de clases
Algunos elementos, particularmente los elementos base como UIElement, exponen mtodos virtuales
"On*Event" y "OnPreview*Event" vacos que corresponden a su lista de eventos enrutados pblicos. Estos
mtodos virtuales se pueden reemplazar para implementar un controlador de clases para ese evento enrutado.
Las clases de elementos base registran estos mtodos virtuales como su controlador de clases para cada uno
de esos eventos enrutados utilizando RegisterClassHandler(Type, RoutedEvent, Delegate, Boolean) tal como se
explic anteriormente. Los mtodos virtuales de On*Event hacen que sea mucho ms fcil implementar el
control de clases para los eventos enrutados pertinentes, sin que sea necesaria una inicializacin especial en
constructores estticos para cada tipo. Por ejemplo, puede agregar el control de clases para el evento
DragEnter en cualquier clase derivada UIElement reemplazando el mtodo virtual OnDragEnter. Dentro del
reemplazo, podra controlar el evento enrutado, desencadenar otros eventos, iniciar lgica especfica de la clase
que podra cambiar las propiedades de elementos en instancias, o cualquier combinacin de esas acciones. En
general, debera llamar a la implementacin base en dichos reemplazos aun cuando marque el evento como
proporciona
un
mtodo
virtual
vaco
OnMouseLeftButtonDown
como
controlador
de
clases
para
la
mayora
de
los
agentes
de
escucha ser
que
los
eventos
MouseLeftButtonDown
MouseLeftButtonUp "desaparecen" y son reemplazados por Click, un evento que tiene ms significado porque
se sabe que este evento tuvo su origen en un verdadero botn y no en alguna parte compuesta del botn o en
algn otro elemento en su totalidad.
Evitar la supresin de eventos por parte de los controles
A veces este comportamiento de supresin de eventos dentro de los controles individuales puede interferir con
intenciones un poco ms generales de lgica de control de eventos para una aplicacin. Por ejemplo, si por
alguna razn su aplicacin tena un controlador para MouseLeftButtonDown situado en el elemento raz de la
aplicacin,
observara
que
cualquier
clic
en
un
botn
del
mouse
no
invocara
los
controladores
dos
tipos
que
forman
parte
de
un
escenario
de
evento
de
cambio
de
propiedad
son
un
tipo
de
informes
de
datos
de
eventos
inusual,
porque
no
se
deriva
de
EventArgs;
de
descriptor
de
acceso
add
para
ese
evento
asociado
atributos
de
evento
nombreDeTipo.nombreDeEvento en XAML.
Para los eventos enrutados, nicamente se puede usar Handles para asignar controladores para instancias para
las que ese evento exista en la tabla de miembros de instancia. Sin embargo, con los eventos enrutados en
general, un elemento primario puede ser un agente de escucha para un evento a partir de los elementos
secundarios, aunque el elemento primario no tenga ese evento en su tabla de miembros. En la sintaxis de
atributo, puede especificar esto mediante un atributo en formato nombreDeTipo.nombreDeMiembro que
certifica cul de los tipos define en realidad el evento que desea controlar. Por ejemplo, un elemento Page
primario (sin ningn evento Click definido) puede realizar escuchas para eventos del clic de botn asignando un
controlador
de
atributo
en
formato
Button.Click.
Sin
embargo,
Handles
no
admite
el
formato
Al registrar los agentes de escucha, no utilice los descriptores de acceso convencionales de agregar y
quitar del evento donde desea que el agente de escucha utilice el modelo. En su lugar, utilice las
implementaciones de "RemoveListener" y "AddListener" del objeto WeakEventManager dedicado para
ese evento.
WeakEventManager
Normalmente, se crean las clases de administrador en relacin 1:1 a los eventos que implementan el modelo.
Por ejemplo, si tiene un evento Spin, derivara una clase SpinEventManager como administrador del evento
dbil dedicado para el evento. Si el evento existe en ms de una clase de origen y, en general, se comporta
igual en todas y comparte el mismo tipo de datos de evento, puede utilizarse el mismo administrador para cada
una de ellas.
La lista de comprobacin de implementacin para derivar de la clase WeakEventManager consiste en invalidar
dos mtodos virtuales y exponiendo diversos miembros ms cuyos nombres no se rigen especficamente por
una plantilla virtual, pero que debe existir de todos modos. Las invalidaciones se utilizan para iniciar o finalizar
el modo de entrega de eventos por la infraestructura de WPF. Los dems miembros son necesarios para
proporcionar funcionalidad que permita que sus propias implementaciones de IWeakEventListener puedan
utilizar WeakEventManager para asociar agentes de escucha al evento.
IWeakEventListener
Una clase que implementa IWeakEventListener tiene una sola responsabilidad: implementar el mtodo de
interfaz ReceiveWeakEvent. La implementacin de ReceiveWeakEvent debe ser centralizada y dirigir cualquier
referencia de evento que exista en esa clase al objeto WeakEventManager adecuado.
Asociar agentes de escucha
Supongamos que tiene un evento ClockwiseSpin (definido por Spinner) que es un evento convencional. Si
desea utilizar el modelo para este evento, debe usar una clase ClockwiseSpinEventManager existente derivada
de WeakEventManager o bien implementarla personalmente. Si tiene una clase de agente de escucha
SpinListener que utilizar como agente de escucha, la tcnica convencional (sin utilizar el modelo) para asociar
el controlador sera emplear la sintaxis +=:
spinnerInstance.ClockwiseSpin += new EventHandler(MyOnCWSpinHandler);
Pero si tiene una clase que implementa IWeakEventListener y que tiene en cuenta el evento ClockwiseSpin y su
administrador en la implementacin, la sintaxis que debe utilizar en su lugar para el modelo WeakEvent es:
ClockwiseSpinEventManager.AddListener(spinnerInstance, this);
A continuacin, la lgica de control del evento se especifica dentro de uno de los casos de la implementacin de
ReceiveWeakEvent en la clase, no como un controlador basado en delegado convencional.
Implementar el modelo para eventos externos
Un aspecto interesante del modelo WeakEvent es que le permite implementar el modelo con un evento que no
forme parte de la base de cdigo. Desde la perspectiva del origen, la manera de asociar los controladores a su
evento no vara, y se controla por WeakEventManager. Slo es necesario definir WeakEventManager para ese
Utilice el mtodo AddHandler, junto con un operador AddressOf, para hacer referencia a la
implementacin del controlador de eventos.
Utilice la palabra clave Handles como parte de la definicin del controlador de eventos. Esta tcnica no
se muestra aqu.
<TextBlock Name="text1">Start by clicking the button below</TextBlock>
<Button Name="b1" Click="MakeButton">Make new button and add handler to it</Button>
Public Partial Class RoutedEventAddRemoveHandler
Private Sub MakeButton(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim b2 As Button = New Button()
b2.Content = "New Button"
AddHandler b2.Click, AddressOf Onb2Click
root.Children.Insert(root.Children.Count, b2)
DockPanel.SetDock(b2, Dock.Top)
text1.Text = "Now click the second button..."
b1.IsEnabled = False
End Sub
Private Sub Onb2Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
text1.Text = "New Button (b2) Was Clicked!!"
End Sub
Nota:
Agregar un controlador de eventos en la pgina XAML analizada inicialmente es mucho ms sencillo.
Dentro del elemento de objeto donde desea agregar el controlador de eventos, agregue un atributo que
coincida con el nombre del evento que desea controlar. A continuacin, especifique el valor de ese
atributo como el nombre del mtodo de control de eventos que defini en el archivo de cdigo
subyacente de la pgina XAML.
clase
UIElement
expone
un
mtodo
virtual
que
habilita
el
control
de
clases
en
el
evento
puede
agregar
directamente
mediante
un
mtodo
de
utilidad
de
la
clase
EventManager,
RegisterClassHandler. nicamente debe llamarse a este mtodo dentro de la inicializacin esttica de clases
que
agregan
el
control
de
clases.
En
este
ejemplo
se
agrega
otro
controlador
para
para
ese
comando
en
concreto,
se
llama
ExecutedRoutedEventHandler
en
En el ejemplo anterior, el comando Paste es el comando, el objeto MenuItem es el origen del comando, el
objeto TextBox es el destino del comando y en enlace del comando lo proporciona el control TextBox. Hay que
indicar que no siempre sucede que el objeto CommandBinding lo suministre el control que es la clase de
destino del comando. Con frecuencia, el objeto CommandBinding debe ser creado por el desarrollador de la
aplicacin; tambin puede ocurrir que el objeto CommandBinding est asociado a un antecesor del destino del
comando.
Commands
Los comandos de WPF se crean implementando la interfaz ICommand. ICommand expone dos mtodos,
Execute y CanExecute, y un evento, CanExecuteChanged. Execute realiza las acciones que estn asociadas al
comando. CanExecute determina si el comando se puede ejecutar en el destino del comando actual. El evento
CanExecuteChanged se produce si el administrador de comandos que centraliza las operaciones de comandos
detecta un cambio en el origen del comando que podra invalidar un comando que se ha iniciado pero que el
enlace de comando an no ha ejecutado. La implementacin de WPF de ICommand es la clase RoutedCommand
y el centro de inters de esta informacin general.
Los principales orgenes de entrada en WPF son el mouse, el teclado, la entrada manuscrita y los comandos
enrutados. Las entradas ms orientadas a dispositivo utilizan un objeto RoutedEvent para notificar a los objetos
de una pgina de aplicacin que se ha producido un evento de entrada. Un RoutedCommand no es diferente.
Los mtodos Execute y CanExecute de una objeto RoutedCommand no contienen la lgica de aplicacin para el
comando, sino que provocan eventos enrutados que se tunelizan y se propagar a travs del elemento hasta que
encuentran un objeto con CommandBinding. El objeto CommandBinding contiene los controladores para estos
eventos y son los controladores los que realizan el comando.
El mtodo Execute de un objeto RoutedCommand provoca los eventos PreviewExecuted y Executed en el
destino del comando. El mtodo CanExecute de un objeto RoutedCommand provoca los eventos CanExecute y
PreviewCanExecute en el destino del comando. Estos eventos se tunelizan y se propagan a travs del rbol de
elementos hasta que encuentran un objeto que tiene un objeto CommandBinding para ese comando en
particular.
proporciona
un
conjunto
de
comandos
enrutados
comunes
distribuido
entre
varias
clases:
CommandParameter es un tipo de datos definido por el usuario utilizado para pasar informacin a los
controladores que implementan el comando.
Las clases WPF que implementan ICommandSource son ButtonBase, MenuItem, Hyperlink y InputBinding.
ButtonBase, MenuItemy Hyperlink invocan un comando cuando se hace clic en ellos y InputBinding invoca un
comando cuando se realiza el InputGesture asociado.
En el ejemplo siguientes se muestra cmo usar un objeto MenuItem en un objeto ContextMenu como origen de
comando para el comando Properties.
<StackPanel>
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Command="ApplicationCommands.Properties" />
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
StackPanel cmdSourcePanel = new StackPanel();
ContextMenu cmdSourceContextMenu = new ContextMenu();
MenuItem cmdSourceMenuItem = new MenuItem();
// Add ContextMenu to the StackPanel.
cmdSourcePanel.ContextMenu = cmdSourceContextMenu;
cmdSourcePanel.ContextMenu.Items.Add(cmdSourceMenuItem);
// Associate Command with MenuItem.
cmdSourceMenuItem.Command = ApplicationCommands.Properties;
Habitualmente, un origen de comando escuchar el evento CanExecuteChanged. Este evento informa al origen
de comando que es posible que haya cambiado la capacidad del comando para ejecutarse en el destino de
comando actual. El origen de comando puede consultar el estado actual del objeto RoutedCommand utilizando
el mtodo CanExecute. El origen de comando se puede deshabilitar a s mismo si no se puede ejecutar el
comando. Un ejemplo de esto es un objeto MenuItem que se atena cuando un comando no se puede ejecutar.
Un objeto InputGesture se puede utilizar como origen de comando. Dos tipos de movimientos de entrada en
WPF son KeyGesture y MouseGesture. Puede pensar en un objeto KeyGesture como en un mtodo abreviado de
teclado, tal como CTRL+C. Un objeto KeyGesture consta de un objeto Key y un conjunto de ModifierKeys. Un
objeto MouseGesture consta de un objeto MouseAction y un conjunto opcional de ModifierKeys.
Para que un InputGesture acte como un origen de comando, debe estar asociado a un comando. Hay varias
maneras de lograrlo. Una manera es utilizar un objeto InputBinding.
En el ejemplo siguiente se muestra cmo crear un objeto KeyBinding entre un objeto KeyGesture y un objeto
RoutedCommand.
mtodos
estticos
para agregar
quitar
controladores
de
eventos
PreviewExecuted,
Executed,
mtodo
InvalidateRequerySuggested
fuerza
al
objeto
CommandManager
provocar
el
evento
RequerySuggested. Esto es til para condiciones que deban deshabilitar o habilitar un comando pero que no
conozca el objeto CommandManager.
Biblioteca de comandos
WPF proporciona un conjunto de comandos predefinidos. La biblioteca de comandos est compuesta de las
clases
siguientes:
ApplicationCommands,
NavigationCommands,
MediaCommands,
EditingCommands
ComponentCommands. Estas clases proporcionan comandos como Cut, BrowseBack y BrowseForward, Play,
Stop y Pause.
Muchos de estos comandos incluyen un conjunto de enlaces de entrada predeterminados. Por ejemplo, si
especifica que la aplicacin administra el comando de copia, obtendr automticamente el enlace de teclado
"CTRL + C". Tambin obtendr los enlaces para otros dispositivos de entrada, como los movimientos de lpiz de
Tablet PC e informacin de voz.
teclado
son
PreviewGotKeyboardFocus, GotKeyboardFocus,
controladores
de
eventos
MouseLeftButtonUp
se
necesita
CommandBinding
para
enlazar
ExecutedRoutedEventHandler
CanExecuteRoutedEventHandler a RoutedCommand.
<Window x:Class="SDKSamples.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MenuItemCommandTask">
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Command="ApplicationCommands.Paste" Width="75" />
</Menu>
<TextBox BorderBrush="Black" BorderThickness="2" Margin="25"
TextWrapping="Wrap">
The MenuItem will not be enabled until
this TextBox gets keyboard focus
</TextBox>
</DockPanel>
</Window>
}
El ltimo paso es el mtodo Execute. Si el comando es RoutedCommand, se llama al mtodo Execute de
RoutedCommand; de lo contrario, se llama al mtodo ICommand Execute.
// If Command is defined, moving the slider will invoke the command;
// Otherwise, the slider will behave normally.
protected override void OnValueChanged(double oldValue, double newValue)
{
base.OnValueChanged(oldValue, newValue);
if (this.Command != null)
{
RoutedCommand command = Command as RoutedCommand;
if (command != null)
{
command.Execute(CommandParameter, CommandTarget);
}
else
{
((ICommand)Command).Execute(CommandParameter);
}
}
}
El diseo general utilizado para crear los recursos para la aplicacin (por pgina, en la aplicacin, en
XAML separado, en un ensamblado slo para recursos).
Recursos estticos
Las referencias de recursos estticos funcionan mejor en las circunstancias siguientes:
Est estableciendo el valor de una propiedad que no est en un objeto DependencyObject o Freezable.
Est creando un diccionario de recursos que se compilar en una DLL y que se empaquetar como
parte de la aplicacin o se compartir entre distintas aplicaciones.
Est creando un tema para un control personalizado y est definiendo recursos que se utilizan dentro
de los temas. En este caso, no es conveniente utilizar el comportamiento de bsqueda de referencia de
recursos dinmicos, sino el comportamiento de referencia de recursos estticos con objeto de que la
bsqueda sea predecible y se circunscriba al tema. Con una referencia de recursos dinmicos, incluso
una referencia dentro de un tema permanecer sin evaluar hasta el tiempo de ejecucin, y existe la
posibilidad de que cuando se aplique el tema, algn elemento local redefina una clave a la que el tema
est intentando hacer referencia, con lo que dicho elemento se encontrar antes que el propio tema
durante la bsqueda. Si este es el caso, el tema no se comportar de la manera esperada.
Est utilizando los recursos para establecer un gran nmero de propiedades de dependencia. Las
propiedades de dependencia permiten el almacenamiento en cach del valor efectivo tal y como ha
sido habilitado por el sistema de propiedades, por lo que si se proporciona un valor para una propiedad
de dependencia que se puede evaluar en el momento de la carga, dicha propiedad no tendr que
comprobar la existencia de una expresin que se ha vuelto a evaluar y podr devolver el ltimo valor
efectivo. Esta tcnica puede suponer una mejora en el rendimiento.
Desea cambiar el recurso subyacente para todos los consumidores o mantener instancias modificables
independientes para cada consumidor utilizando Atributo x:Shared.
2.
3.
Por ltimo, se comprueban los recursos de la aplicacin. Los recursos de la aplicacin son los
existentes dentro del diccionario de recursos definido por el objeto Application para la aplicacin de WPF.
El valor del recurso depende de condiciones que no se conocen hasta el tiempo de ejecucin. Esto
incluye los recursos del sistema, o los recursos que de otra forma seran establecidos por el usuario.
Por ejemplo, puede crear valores de establecedor que hacen referencia a las propiedades del sistema,
de la forma expuesta por SystemColors, SystemFonts o SystemParameters. Estos valores son
autnticamente dinmicos porque proceden del entorno en tiempo de ejecucin del usuario y del
sistema operativo. Tambin es posible tener temas de nivel de aplicacin que pueden cambiar, en los
que el acceso a recursos de nivel de pgina tambin debe capturar los cambios.
Est creando o haciendo referencia a los estilos del tema para un control personalizado.
Dispone de una estructura de recursos compleja que tiene interdependencias, y en la que es posible
que se necesite una referencia adelantada. A diferencia de las referencias de recursos estticos, las
referencias de recursos dinmicos admiten las referencias adelantadas, ya que no es necesario evaluar
el recurso hasta el tiempo de ejecucin y, por consiguiente, las referencias adelantadas no son un
concepto pertinente.
Est haciendo referencia a un recurso que es de gran tamao desde la perspectiva de un espacio de
compilacin o de trabajo, y es posible que dicho recurso no se utilice inmediatamente al cargar la
pgina. Las referencias de recursos estticos siempre se cargan desde XAML al cargar la pgina; sin
embargo, una referencia de un recurso dinmico no lo hace hasta que se utiliza realmente.
Est creando un estilo cuyos valores de establecedor podran proceder de otros valores influenciados
por los temas o por otras configuraciones del usuario.
Est aplicando recursos a elementos que podran haber cambiado de elemento primario en el rbol
lgico durante la duracin de la aplicacin. Al cambiar el elemento primario, tambin se cambia
potencialmente el mbito de bsqueda de recursos, por lo que si desea que el recurso para un
elemento que ha cambiado de elemento primario se vuelva a evaluar dependiendo del nuevo mbito,
siempre debe utilizar una referencia de recurso dinmico.
2.
3.
Por ltimo, se comprueban los recursos de la aplicacin. Los recursos de la aplicacin son los
existentes dentro del diccionario de recursos definido por el objeto Application para la aplicacin de WPF.
4.
5.
Si una llamada a FindResource solicita un recurso, y ste no se encuentra, se inicia una excepcin.
Restricciones
Las referencias de recursos dinmicos tienen algunas restricciones importantes. Al menos debe cumplirse una
de las condiciones siguientes:
Nota:
Es vlido definir recursos dentro de un objeto ResourceDictionary especificado como diccionario combinado,
ya sea como alternativa a especificar la propiedad Source, o bien adems de los recursos incluidos desde el
origen especificado. Sin embargo, ste no es un escenario comn; el escenario principal para los
diccionarios combinados es combinar recursos procedentes de ubicaciones de archivo externas. Si desea
especificar los recursos dentro del marcado de una pgina, deber definirlos en el objeto
ResourceDictionary principal, y no en los diccionarios combinados.
Comportamiento de los diccionarios combinados
Los recursos de un diccionario combinado ocupan una ubicacin en el mbito de bsqueda de recursos que se
encuentra justo despus del mbito del diccionario de recursos principal con el que se combinan. Aunque una
clave de recurso debe ser nica dentro de cualquier diccionario individual, una clave puede existir varias veces
en un conjunto de diccionarios combinados. En este caso, el recurso que se devuelve proceder del ltimo
diccionario situado secuencialmente en la coleccin MergedDictionaries. Si la coleccin MergedDictionaries se ha
definido en XAML, entonces el orden de los diccionarios combinados de la coleccin es el orden de los
elementos que se indica en el marcado. Si una clave est definida en el diccionario principal y tambin en un
diccionario que se ha combinado, entonces el recurso que se devuelve proceder del diccionario principal. Estas
reglas de mbito se aplican igualmente para referencias de recursos estticos y referencias de recursos
dinmicos.
Diccionarios combinados y cdigo
Los diccionarios combinados se pueden agregar a un diccionario Resources mediante cdigo. El objeto
ResourceDictionary predeterminado inicialmente vaco que existe para cualquier propiedad Resources tambin
tiene una propiedad de coleccin MergedDictionaries predeterminada inicialmente vaca. Para agregar un
diccionario combinado mediante cdigo, se obtiene una referencia al objeto ResourceDictionary primario
deseado, se obtiene el valor de su propiedad MergedDictionaries y se llama a Add en la Collection genrica
contenida en MergedDictionaries. El objeto que se agrega debe ser un nuevo ResourceDictionary. En el cdigo,
no se establece la propiedad Source. En cambio, se debe obtener un objeto ResourceDictionary creando o
cargando uno. Una manera de cargar un ResourceDictionary existente consiste en llamar a XamlReader.Load en
una secuencia de archivo XAML existente que tiene un ResourceDictionary raz y, a continuacin, convertir el
valor devuelto de XamlReader.Load a ResourceDictionary.
URI de diccionarios de recursos combinados
Existen varias tcnicas para incluir un diccionario de recursos combinado, que vienen dadas por el formato de
identificador de recursos uniforme (URI) que se utilizar. En lneas generales, estas tcnicas se pueden dividir
en dos categoras: los recursos que se compilan como parte del proyecto y recursos que no se compilan como
parte del proyecto.
Para los recursos que se compilan como parte del proyecto, puede utilizar una ruta de acceso relativa que hace
referencia a la ubicacin del recurso. La ruta de acceso relativa se evala durante la compilacin. El recurso se
debe definir como parte del proyecto como una accin de compilacin de recurso. Si incluye un archivo .xaml
de recursos en el proyecto como recurso, no ser preciso copiar el archivo de recursos en el directorio de
resultados, el recurso ya est incluido dentro de la aplicacin compilada. Tambin puede utilizar la accin de
compilacin de contenido, pero en este caso deber copiar los archivos en el directorio de resultados y tambin
implementar los archivos de recursos en la misma relacin de ruta de acceso que la aplicacin ejecutable.
Nota:
No utilice la accin de compilacin de recurso incrustado. La propia accin de compilacin se admite para
aplicaciones de WPF, pero la resolucin de Source no incorpora ResourceManager, por lo que no puede
separar el recurso individual de la secuencia. Podra utilizar la accin de recurso incrustado para otros fines,
siempre que, adems, utilice ResourceManager para tener acceso a los recursos.
Una tcnica relacionada es utilizar un pack URI a un archivo de XAML y hacer referencia a l como el origen. El
pack URI permite las referencias a los componentes de ensamblados a los que se hace referencia, y otras
tcnicas.
ejemplo,
FullPrimaryScreenHeight
es
un
valor
de
la
propiedad
SystemParameters
Esta informacin general se centra en los aspectos de estilos y plantillas de la aplicacin y no aborda los
conceptos de enlace de datos.
Adems, es importante entender los recursos, que permiten reutilizar los estilos y las plantillas.
Fundamentos de estilos
Puede considerar un objeto Style como una manera cmoda de aplicar un conjunto de valores de propiedades a
ms de un elemento. Por ejemplo, considere los siguientes elementos
TextBlock y su apariencia
predeterminada:
<TextBlock>My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>
Este estilo TitleText extiende el estilo creado para el tipo TextBlock. Tambin puede extender un estilo que
tenga un atributo x:Key utilizando el valor de x:Key. Para ver un ejemplo, vea el que se proporciona para la
propiedad BasedOn.
Relacin entre la propiedad TargetType y el atributo x:Key
de
los
objetos
Setter
con
un
nombre
de
clase,
utilizando
la
sintaxis
La mayora de los controles tienen algn tipo de contenido y ese contenido suele proceder de los datos a los
que se est enlazando. En este ejemplo, los datos son la lista de fotos. En WPF, utilice DataTemplate para
definir la representacin visual de los datos. Bsicamente, el contenido de DataTemplate determina la
apariencia de los datos en la aplicacin representada.
En la aplicacin de ejemplo, cada objeto Photo personalizado tiene una propiedad Source de tipo cadena que
especifica la ruta de acceso del archivo de imagen. Actualmente, los objetos de foto aparecen como rutas de
acceso de archivo.
Para que las fotos aparezcan como imgenes, debe crear un objeto DataTemplate como un recurso:
<Window.Resources>
...
<!--DataTemplate to display Photos as images
instead of text strings of Paths-->
<DataTemplate DataType="{x:Type local:Photo}">
<Border Margin="3">
<Image Source="{Binding Source}"/>
</Border>
</DataTemplate>
...
</Window.Resources>
Observe que la propiedad DataType es muy similar a la propiedad TargetType de Style. Si DataTemplate est
en la seccin de recursos, al especificar la propiedad DataType en un tipo y no asignarle un atributo x:Key,
DataTemplate se aplicar cada vez que aparezca ese tipo. Siempre tiene la opcin de asignar a DataTemplate
un atributo x:Key y, a continuacin, establecerlo como StaticResource para las propiedades que admiten tipos
DataTemplate, como la propiedad ItemTemplate o la propiedad ContentTemplate.
El objeto DataTemplate del ejemplo anterior define esencialmente que, siempre que haya un objeto Photo, ste
debe aparecer como un control Image dentro de un control Border. Con este objeto DataTemplate, la aplicacin
tiene ahora esta apariencia:
El modelo de plantillas de datos proporciona otras caractersticas. Por ejemplo, si se muestran datos de
coleccin que contengan otras colecciones con un tipo HeaderedItemsControl como un control Menu o un
control TreeView, ah est el objeto HierarchicalDataTemplate. Otra caracterstica de las plantillas de datos es el
objeto DataTemplateSelector, que permite elegir el objeto DataTemplate que se va a utilizar basndose en una
lgica personalizada.
Plantillas de control
Este tema contiene las subsecciones siguientes.
Propiedad IsItemsHost
ItemsPresenter y ContentPresenter
TemplateBinding
Ahora que las fotos aparecen como imgenes, vamos a mostrarlas horizontalmente en lugar de verticalmente;
el control ListBox se va a mostrar horizontalmente.
Sin utilizar ControlTemplate
En primer lugar, es importante sealar que no es necesario utilizar el objeto ControlTemplate para que el
control ListBox sea horizontal. ListBox tiene la propiedad ItemsPanel, que permite establecer un objeto
ItemsPanelTemplate, la plantilla que controla el diseo de los elementos del control ListBox. Una opcin es
crear simplemente un estilo de ListBox y establecer la propiedad ItemsPanel, como en el ejemplo siguiente:
<Style TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Este procedimiento funciona bien y el resultado es un control ListBox horizontal. En este ejemplo se muestra
que, dependiendo del escenario, puede haber otras opciones adems de reemplazar el objeto ControlTemplate.
Para este ejemplo, si deseamos obtener un control ListBox horizontal que tenga propiedades adicionales, como
esquinas redondeadas, necesitamos trabajar con el objeto ControlTemplate del control ListBox.
Antes de proporcionar un ejemplo para mostrar cmo hacerlo, es importante explicar primero el concepto de
ControlTemplate.
Qu es ControlTemplate?
La mayora de controles tienen una apariencia y un comportamiento. Considere un botn: la apariencia es el
rea elevada que se puede presionar y el comportamiento es el evento Click que se provoca en respuesta a un
clic.
En ocasiones, puede haber un control que proporcione el comportamiento necesario, pero no la apariencia
necesaria. Hasta ahora, hemos mostrado que puede utilizar establecedores de estilo para establecer valores de
propiedad que afecten a la apariencia del control. Sin embargo, para cambiar la estructura de un control o
establecer valores de propiedad en los componentes de un control, debe utilizar un objeto ControlTemplate.
En WPF, el objeto ControlTemplate de un control define su apariencia. Puede cambiar la estructura y la
apariencia de un control definiendo un nuevo objeto ControlTemplate para el control. En muchos casos, esto
ofrece suficiente flexibilidad como para no tener que escribir controles personalizados. Si no define un objeto
ControlTemplate propio para el control, debe obtener la plantilla predeterminada que se ajuste al tema del
sistema; es esta plantilla la que da la apariencia predeterminada al control Button.
Recuerde que al crear un objeto ControlTemplate para el control, se reemplaza el objeto ControlTemplate
completo. Por ejemplo, puede definir el objeto ControlTemplate de un control Button de la manera siguiente.
Observe que el elemento ContentPresenter simplemente marca dnde debe ir la propiedad Content del control
Button. Explicaremos las diferentes partes en una seccin posterior.
<Style TargetType="Button">
<!--Set to true to not get any properties from the themes.-->
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
Recuerde que la apariencia que presenta el control Button cuando tiene el foco o est presionado forma parte
de la apariencia predeterminada del botn que est reemplazando. Por consiguiente, en funcin de sus
necesidades, quiz desee incluir en la definicin la apariencia que debe tener el botn cuando est presionado.
Cuando cree un objeto ControlTemplate, la mejor manera de empezar es utilizar los Ejemplos de
ControlTemplate. Si realmente necesita examinar las partes de las que se compone un control, puede echar una
mirada al archivo de temas ubicado en Temas o puede utilizar la funcionalidad Show Visual Tree de XAMLPad,
una aplicacin que se instala con Kit de desarrollo de software de Windows (SDK).
Crear un objeto ControlTemplate
Ahora, vamos a continuar con nuestro ejemplo y crear un objeto ControlTemplate que defina un control ListBox
horizontal y con esquinas redondeadas. Para reemplazar el objeto ControlTemplate de un control, establezca la
propiedad Template en el nuevo objeto ControlTemplate.
<Style TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border CornerRadius="5" Background="{TemplateBinding ListBox.Background}">
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"
HorizontalAlignment="Center" IsItemsHost="True"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Cuando se establece la propiedad Template de esta manera, no hay realmente ninguna diferencia con el
establecimiento de otras propiedades de control mediante Style: se usa un objeto Style como una herramienta
que ayuda a establecer la propiedad Template. Esto significa que otra manera de establecer un objeto
ControlTemplate es establecer directamente la propiedad Template en el control. Si procede de esta manera,
crea un objeto ControlTemplate en la seccin Resources, le asigna un atributo x:Key y, a continuacin, lo utiliza
como un recurso esttico.
Como puede ver en el ejemplo anterior, la clase ControlTemplate tiene una propiedad TargetType que es similar
a la propiedad TargetType de la clase Style. No obstante, observe que, a diferencia de Style y DataTemplate,
los objetos ControlTemplate no tienen la nocin de una clave implcita. En otras palabras, si tiene un objeto
ControlTemplate independiente con la propiedad TargetType establecida en un tipo, el objeto ControlTemplate
no se aplicar automticamente a ese tipo. Observe tambin que se requiere la propiedad TargetType en un
objeto ControlTemplate si la definicin de la plantilla contiene un objeto ContentPresenter.
Experimente con el objeto ControlTemplate. Por ejemplo, reemplace el control StackPanel con un control
WrapPanel, establezca la propiedad HorizontalScrollBarVisibility del control ScrollViewer en Disabled y, a
continuacin, establezca el ancho del control ListBox en 300. (WrapPanel solamente coloca elementos en la fila
siguiente cuando la primera fila se queda sin espacio. Si no establece la propiedad HorizontalScrollBarVisibility
del control ScrollViewer en Disabled, la primera fila no se queda sin espacio porque es posible desplazarse hasta
el final. Como resultado, el control WrapPanel no ajusta los elementos.)
Propiedad IsItemsHost
En este ejemplo, una propiedad importante que debe estar presente es la propiedad IsItemsHost. La propiedad
IsItemsHost se utiliza para indicar en la plantilla de un control ItemsControl (controles como ListBox que tienen
una lista de elementos) dnde deben ir los elementos generados. Si se establece la propiedad en true en el
Desencadenadores
Style, ControlTemplate y DataTemplate tienen una propiedad Triggers que puede contener un conjunto de
desencadenadores. Un desencadenador establece propiedades o inicia acciones, como animaciones, cuando
cambia un valor de propiedad o cuando se provoca un evento.
Este tema contiene las subsecciones siguientes.
Desencadenadores de propiedades
Desencadenadores de eventos y guiones grficos
MultiTrigger, DataTrigger y MultiDataTrigger
Desencadenadores de propiedades
Para mostrar cmo se utilizan los desencadenadores para establecer propiedades, hagamos que cada elemento
ListBoxItem sea parcialmente transparente a menos que est seleccionado.
Si se fija en los archivos XAML del ejemplo, observar que todos los archivos tienen lo siguiente:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>
Es el uso compartido de shared.xaml, que define un objeto ResourceDictionary que contiene un conjunto de
recursos de estilo y de pincel que permite que los controles del ejemplo tengan una apariencia coherente.
2.
Se evalan las propiedades de tamao definidas en FrameworkElement, como Width, Height y Margin.
3.
4.
Este proceso, y los medios por los que se invoca, se define con mayor detalle en las secciones siguientes.
Rectngulos de seleccin de elementos
Al pensar en el diseo de una aplicacin en Windows Presentation Foundation (WPF), es importante entender el
rectngulo de seleccin que rodea todos los elementos. Esta abstraccin ayuda a comprender el
comportamiento del sistema de diseo. Cada FrameworkElement utilizado por el sistema de diseo se puede
considerar como un rectngulo que se inserta en una particin del diseo. Se expone una clase,
LayoutInformation, que puede devolver los lmites geomtricos de la asignacin de diseo de un elemento, o su
ranura. El sistema, calculando el espacio de pantalla disponible, determina el tamao de ese rectngulo, el
tamao de cualquier restriccin, las propiedades especficas del diseo, como el margen y el relleno, y el
comportamiento individual del elemento Panel primario. Al procesar estos datos, el sistema puede calcular la
posicin de todos los elementos secundarios de un Panel determinado. Es importante recordar que las
caractersticas de tamao definidas en el elemento primario (como un Border) afectan a sus elementos
secundarios.
Como ejemplo, tomemos el siguiente escenario de diseo simple.
Este diseo se puede lograr utilizando el Lenguaje de marcado de aplicaciones extensible (XAML) siguiente.
<Grid Name="myGrid" Background="LightSteelBlue" Height="150">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Name="txt1" Margin="5" FontSize="16" FontFamily="Verdana" Grid.Column="0"
Grid.Row="0">Hello World!</TextBlock>
<Button Click="getLayoutSlot1" Width="125" Height="25" Grid.Column="0"
Grid.Row="1">Show Bounding Box</Button>
<TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
</Grid>
El elemento TextBlock solitario se hospeda dentro de una Grid. Aunque el texto rellena slo la esquina superior
izquierda de la columna en la que se ha colocado, en realidad el espacio asignado para TextBlock es mucho
mayor. El rectngulo de seleccin de cualquier objeto FrameworkElement se puede recuperar utilizando el
mtodo GetLayoutSlot. Con este mtodo, el rectngulo de seleccin del elemento TextBlock queda superpuesto
(esto es posible porque el TextBlock se hospeda en una Grid, un elemento Panel que permite compartir las
coordenadas de diseo).
Como queda claro ahora por la lnea blanca que lo rodea, la particin asignada al elemento TextBlock es, en
realidad, mucho mayor que el espacio que rellena. Al agregar elementos adicionales a Grid, esta asignacin se
puede reducir o expandir, dependiendo del tipo y el tamao de los elementos que se agregan.
La ranura de diseo de TextBlock se devuelve y convierte en un Path mediante el mtodo GetLayoutSlot, una
tcnica que puede resultar til para mostrar el rectngulo de seleccin de un elemento.
Private Sub getLayoutSlot1(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim myRectangleGeometry As New RectangleGeometry
myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1)
Nombre del
panel
Descripcin
Canvas
Define una rea en la que pueden colocarse explcitamente los elementos secundarios
utilizando las coordenadas relativas al rea del control Canvas.
DockPanel
Grid
StackPanel
Organiza los elementos secundarios en una nica lnea que se puede orientar horizontal
o verticalmente.
VirtualizingPanel
WrapPanel
Para los escenarios que requieren un diseo de aplicacin que no es posible utilizando cualquiera de los
elementos Panel predefinidos, se pueden conseguir comportamientos de diseo personalizados heredando de
Panel e invalidando los mtodos MeasureOverride y ArrangeOverride.
Consideraciones sobre el rendimiento del diseo
El diseo es un proceso recursivo. Cada elemento secundario de una coleccin Children se procesa durante
cada invocacin del sistema. Como resultado, debe evitarse activar el sistema cuando no es necesario. Las
sugerencias siguientes pueden ayudarle a lograr un rendimiento ms alto.
Las propiedades de dependencia cuyos valores pueden hacer que el sistema de diseo se inicialice se marcan
con marcadores pblicos. AffectsMeasure y AffectsArrange proporcionan pistas tiles sobre qu cambios del
valor de la propiedad forzarn una actualizacin recursiva del sistema del diseo. En general, cualquier
propiedad que puede afectar al tamao del rectngulo de seleccin de un elemento debera establecer la marca
AffectsMeasure en true.
LayoutTransform puede ser una manera muy til de afectar al contenido de una interfaz de usuario (UI). Sin
embargo, si no es necesario que el efecto de la transformacin afecte a la posicin de otros elementos, es
mejor utilizar RenderTransform en su lugar, ya que RenderTransform no invoca el sistema del diseo.
LayoutTransform aplica su transformacin y fuerza una actualizacin del diseo recursiva para tener en cuenta
la nueva posicin del elemento afectado.
Evite las llamadas innecesarias a UpdateLayout. Este mtodo fuerza una actualizacin del diseo recursiva y no
suele ser necesario. A menos que est seguro de que se requiere una actualizacin completa, deje que el
sistema de diseo llame a este mtodo en su lugar.
Al tratar con una coleccin Children grande, puede ser conveniente utilizar VirtualizingStackPanel en lugar de
un StackPanel normal. Al "virtualizar" la coleccin secundaria, VirtualizingStackPanel nicamente conserva en la
memoria los objetos que se encuentran actualmente dentro del rea de visualizacin del elemento primario.
Como resultado, el rendimiento se mejora sustancialmente en la mayora de los escenarios.
el
ajuste
de
pxeles,
las
lneas
representadas
con
suavizado
(anti-aliasing)
pueden
parecer
semitransparentes si el borde no se encuentra entre los pxeles del dispositivo. En la ilustracin siguiente se
muestra el resultado de representar con suavizado una lnea con un grosor de un solo pxel cuando se
encuentra en medio de un pxel del dispositivo (izquierda) y cuando se encuentra entre pxeles del dispositivo
(derecha).
Representacin de lnea con suavizado.
Con el ajuste de pxeles, las lneas suavizadas se ajusta, o fijan, a los pxeles del dispositivo y parecen ntidas,
con lo que se elimina la representacin de lneas semitransparentes. En el ejemplo siguiente se muestra el
efecto de la propiedad SnapsToDevicePixels en una lnea con un grosor de un solo pxel. Al cambiar lentamente
el tamao de la ventana, se muestran las anomalas que aparecen en una lnea no ajustada (izquierda) y el
tamao fijo de la lnea que s se ha ajustado (derecho) a medida que cambia su posicin.
<Page x:Class="PixelSnapping.Lines"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Lines" Name="linesPage">
<StackPanel Width="150" Margin="7" Orientation="Horizontal">
<!-- Single pixel line with pixel snapping turned OFF.-->
<Rectangle SnapsToDevicePixels="False"
Width="45.5" Margin="10" Height="1" Fill="Red"/>
<!-- Single pixel line with pixel snapping turned ON.-->
<Rectangle SnapsToDevicePixels="True"
Width="45.5" Margin="10" Height="1" Fill="Red"/>
</StackPanel>
<!-- Background Grid -->
<Page.Background>
<DrawingBrush Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
<GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Page.Background>
</Page>
Nota:
SnapsToDevicePixels nicamente afecta a los elementos que se encuentran en el recorrido de la pasada
de diseo. Pueden establecerse lneas de gua en un objeto Drawing mediante la propiedad GuidelineSet
del objeto DrawingGroup. Para establecer manualmente las lneas de gua de un objeto Visual, cree
nuevas lneas de gua mediante las propiedades VisualYSnappingGuidelines y VisualXSnappingGuidelines.
El ajuste de pxeles nicamente afecta a la nitidez de las lneas horizontales y verticales, no afecta a las lneas
diagonales.
Con el ajuste de pxeles habilitado, los bordes colindantes se ajustan a los pxeles del dispositivo para quitar el
efecto de permeabilidad. En el ejemplo siguiente se muestra el efecto de la propiedad SnapsToDevicePixels en
objetos colindantes. Al cambiar lentamente el tamao de la ventana, se presenta el problema de permeabilidad
en los rectngulos sin ajustar (izquierda), mientras que en los rectngulos ajustados (derecha) permanecen
unidos sin irregularidades visuales.
<Page x:Class="PixelSnapping.Seeping"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Seeping">
<StackPanel Orientation="Horizontal" Height="100">
<Border
SnapsToDevicePixels="False"
Margin="10" BorderThickness="1" BorderBrush="Black" Height="80"
Background="White">
<StackPanel Height="100.0">
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
</StackPanel>
</Border>
<Border
SnapsToDevicePixels="True"
Margin="10" BorderThickness="1" BorderBrush="Black" Height="80"
Background="White">
<StackPanel Height="100.0">
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
<Rectangle Width="20" Height="20" Fill="Red"/>
</StackPanel>
</Border>
</StackPanel>
<!-- Background Grid -->
<Page.Background>
<DrawingBrush Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
<GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Page.Background>
</Page>
Foundation
(WPF)
detecta
cualquier
movimiento
similar
una
animacin,
como
un
desplazamiento, un ajuste de escala o una conversin animada, el ajuste de pxeles se desactiva hasta que se
completa el movimiento. Cuando la animacin o el movimiento de desplazamiento termina, se vuelve a animar
lentamente el ajuste de pxeles.
Lneas de gua
Bsicamente, el ajuste de pxeles se controla mediante lneas de gua. Las lneas de gua ayudan a ajustar las
geometras a una cuadrcula de pxeles del dispositivo. En la mayora de los casos, el ajuste de pxeles mediante
la propiedad SnapsToDevicePixels da lugar al resultado deseado. Sin embargo, esta propiedad no siempre est
disponible, sobre todo cuando se utilizan objetos Drawing o se trata directamente con un DrawingContext; en
estos casos es preciso establecer lneas de gua para lograr la nitidez deseada que el ajuste de pxeles
proporciona.
Para establecer las lneas de gua en los objetos Drawing y DrawingContext, se utiliza la clase GuidelineSet.
Esta clase permite crear lneas de gua horizontales y verticales que se pueden aplicar a DrawingGroup o se
puedan insertar en DrawingContext para los comandos de dibujo subsiguientes. Las lneas de gua indican al
dibujo qu lneas se deben ajustar a un pxel del dispositivo.
Las lneas de gua tambin se pueden establecer en el nivel de los objetos Visual cambiando las colecciones de
lneas
de
gua
horizontales
verticales.
Se
tiene
acceso
ellas
travs
de
las
propiedades
VisualYSnappingGuidelines y VisualXSnappingGuidelines.
Imgenes de mapa de bits
Debido al carcter independiente de dpi de WPF, las interfaz de usuario basadas en mapas de bits pueden dar
lugar a resultados de presentacin no deseados. Las escenas con suavizado (anti-aliasing) pueden emborronar
una imagen a causa de los problemas de alineacin de los pxeles fraccionarios. Esto se cumple en particular
para las imgenes que contienen cambios de alta frecuencia, tales como las lneas de un solo pxel con
elementos adyacentes en contraste (como lneas negras y blancas alternas). En la ilustracin siguiente se
muestran las diferencias de calidad de imagen de una imagen alineada (izquierda) y una imagen desplazada de
modo que no est alineada con los pxeles del dispositivo (derecho).
Alineacin de la imagen con los pxeles del dispositivo.
Un escenario comn para las imgenes de una interfaz de usuario es centrar una imagen que representa un
icono dentro de otro objeto. Dado que los iconos suelen ser imgenes pequeas con cambios de alta frecuencia,
puede ser preciso ajustar el diseo de la aplicacin para evitar las anomalas visuales generadas por el
suavizado (anti-aliasing).
Para centrar correctamente una imagen, el contenedor debe tener un ancho y un alto pares si el ancho y el alto
en pxeles de la imagen son pares. Si el ancho y el alto de la imagen son impares, el ancho y el alto del
elemento contenedor tambin debern ser impares.
<Page x:Class="PixelSnapping.Images"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Images">
<StackPanel>
<!-- Image has a pixel dimension of 144x96. -->
<!-- Because the image has a even width and height,
an even border width and height allows the image to proper center.
-->
<Border HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Height="100">
<Image HorizontalAlignment="Center" VerticalAlignment="Center"
Source="sharpness.png" Stretch="None"/>
</Border>
<!-- Image has a pixel dimension of 144x96. -->
<!-- Because the image has a even width and height,
an odd border width and height causes the image to soften.
-->
<Border HorizontalAlignment="Left" VerticalAlignment="Top" Width="201" Height="101">
<Image HorizontalAlignment="Center" VerticalAlignment="Center"
Source="sharpness.png" Stretch="None"/>
</Border>
</StackPanel>
<!-- Grid Background -->
<Page.Background>
<DrawingBrush Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
<GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Page.Background>
</Page>
Por desgracia, la alineacin con los pxeles del dispositivo no se garantiza con slo ajustar el tamao del objeto
contenedor. El diseo de la aplicacin en su conjunto puede afectar a la alineacin de la imagen. El valor de
puntos por pulgada (dpi) de pantalla tambin afecta a la alineacin de las imgenes. En el ejemplo anterior, la
alineacin de la imagen funcionar nicamente si la pantalla est establecida en 96 puntos por pulgada (dpi).
Con cualquier otra configuracin, deber ajustarse el diseo a fin de alojar la configuracin de pantalla.
Siempre que sea posible, deben evitarse las imgenes de alta frecuencia en las aplicaciones de Windows
Presentation Foundation (WPF).
implica
un
clculo
grande
necesita
consultar
una
base
de
datos
de
algn
servidor
Esta sencilla aplicacin cuenta en orden ascendente desde tres, buscando nmeros primos. Cuando el usuario
hace clic en el botn Inicio, la bsqueda comienza. Cuando el programa encuentra un nmero primo, actualiza
la interfaz de usuario con su deteccin. En cualquier punto, el usuario puede detener la bsqueda.
Aunque es bastante simple, la bsqueda de nmeros primos podra continuar para siempre, lo que presenta
algunas dificultades. Si administrramos toda la bsqueda completa dentro del controlador del evento clic del
botn, nunca daramos al subproceso de la interfaz de usuario la oportunidad de administrar otros eventos. La
interfaz de usuario no podra responder a entradas ni mensajes del proceso. Nunca actualizara la pantalla ni
respondera a clics del mouse.
Podramos realizar la bsqueda de nmeros primos en un subproceso independiente, pero entonces
encontraramos problemas de sincronizacin. Con un enfoque de un nico subproceso, podemos actualizar
directamente la etiqueta que muestra el mayor nmero encontrado.
Si dividimos la tarea de clculo en fragmentos manejables, podemos volver peridicamente a los eventos de
Dispatcher y de proceso Podemos dar una oportunidad a WPF para que vuelva a dibujar y procesar la entrada.
La mejor forma de dividir el tiempo de proceso entre el clculo y el control de eventos es administrar el clculo
desde el objeto Dispatcher. Utilizando el mtodo BeginInvoke, podemos programar las comprobaciones de
nmeros primos en la misma cola de la que se extraen los eventos de la interfaz de usuario. En nuestro
ejemplo, programamos solamente una comprobacin de nmero primo cada vez. Una vez completada la
comprobacin del primer nmero primo, programamos inmediatamente la siguiente comprobacin. Esta
comprobacin slo contina una vez administrados los eventos de la interfaz de usuario pendientes.
Microsoft Word realiza la revisin ortogrfica mediante este mecanismo. La revisin ortogrfica se hace en
segundo plano utilizando el tiempo de inactividad del subproceso de la interfaz de usuario. Echemos una mirada
al cdigo.
En el ejemplo siguiente se muestra el XAML que crea la interfaz de usuario.
<Window x:Class="SDKSamples.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Prime Numbers" Width="260" Height="75">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" >
<Button Content="Start" Click="StartOrStop" Name="startStopButton"
Margin="5,0,5,0"/>
<TextBlock Margin="10,5,0,0">Biggest Prime Found:</TextBlock>
<TextBlock Name="bigPrime" Margin="4,5,0,0">3</TextBlock>
</StackPanel>
</Window>
En el cdigo siguiente se muestra el cdigo subyacente:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Threading;
namespace SDKSamples
{
public partial class Window1 : Window
{
public delegate void NextPrimeDelegate();
//Current number to check
private long num = 3;
private bool continueCalculating = false;
public Window1() : base()
{
InitializeComponent();
}
private void StartOrStop(object sender, EventArgs e)
{
if (continueCalculating)
{
continueCalculating = false;
startStopButton.Content = "Resume";
}
else
{
continueCalculating = true;
startStopButton.Content = "Stop";
startStopButton.Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
new NextPrimeDelegate(CheckNextNumber));
}
}
public void CheckNextNumber()
{
// Reset flag.
NotAPrime = false;
for (long i = 3; i <= Math.Sqrt(num); i++)
{
if (num % i == 0)
{
// Set not a prime flag to ture.
NotAPrime = true;
break;
}
}
// If a prime number.
if (!NotAPrime)
{
bigPrime.Text = num.ToString();
}
num += 2;
if (continueCalculating)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Threading;
namespace SDKSamples
{
public partial class Window1 : Window
{
// Delegates to be used in placking jobs onto the Dispatcher.
private delegate void NoArgDelegate();
private delegate void OneArgDelegate(String arg);
// Storyboards for the animations.
private Storyboard showClockFaceStoryboard;
private Storyboard hideClockFaceStoryboard;
private Storyboard showWeatherImageStoryboard;
private Storyboard hideWeatherImageStoryboard;
public Window1(): base()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Load the storyboard resources.
showClockFaceStoryboard =
(Storyboard)this.Resources["ShowClockFaceStoryboard"];
hideClockFaceStoryboard =
(Storyboard)this.Resources["HideClockFaceStoryboard"];
showWeatherImageStoryboard =
(Storyboard)this.Resources["ShowWeatherImageStoryboard"];
hideWeatherImageStoryboard =
(Storyboard)this.Resources["HideWeatherImageStoryboard"];
}
private void ForecastButtonHandler(object sender, RoutedEventArgs e)
{
// Change the status image and start the rotation animation.
fetchButton.IsEnabled = false;
fetchButton.Content = "Contacting Server";
weatherText.Text = "";
hideWeatherImageStoryboard.Begin(this);
// Start fetching the weather forecast asynchronously.
NoArgDelegate fetcher = new NoArgDelegate(this.FetchWeatherFromServer);
fetcher.BeginInvoke(null, null);
}
private void FetchWeatherFromServer()
}
}
A continuacin se muestran algunos de los detalles que se deben tener en cuenta.
WPF
crea
automticamente
un
nuevo
objeto
Dispatcher
para
administrar
el
nuevo
subproceso. Todo lo que tenemos que hacer para que la ventana sea funcional es iniciar el objeto Dispatcher.
Detalles tcnicos y puntos problemticos
Escribir componentes usando subprocesos
La Gua del desarrollador de Microsoft .NET Framework describe un modelo de cmo un componente puede
exponer comportamiento asincrnico a sus clientes. Por ejemplo, suponga que deseamos empaquetar el
mtodo FetchWeatherFromServer en un componente reutilizable, no grfico. Siguiendo el modelo de Microsoft
.NET Framework estndar, tendra un aspecto similar al siguiente.
public class WeatherComponent : Component
Algn subproceso debe estar a cargo de la ventana de cuadro de mensaje. WPF podra crear simplemente un
nuevo subproceso para la ventana de cuadro de mensaje, pero este subproceso no podra representar los
elementos deshabilitados en la ventana original (recuerde la explicacin anterior sobre la exclusin mutua). En
su lugar, WPF utiliza un sistema de procesado de mensajes anidados. La clase Dispatcher incluye un mtodo
especial denominado PushFrame, que almacena el punto de ejecucin actual de una aplicacin y, a
continuacin, comienza un nuevo bucle de mensajes. Cuando finaliza el bucle de mensajes anidados, la
ejecucin se reanuda despus de la llamada original a PushFrame.
En este caso, PushFrame mantiene el contexto de programa en la llamada a MessageBox.Show e inicia un
nuevo bucle de mensajes para actualizar la ventana de fondo y administrar la entrada en la ventana de cuadro
de mensaje. Cuando el usuario hace clic en Aceptar y borra la ventana emergente, se sale del bucle anidado y
se reanuda el control despus de la llamada a Show.
Eventos enrutados obsoletos
El sistema de eventos enrutados de WPF notifica a los rboles completos cuando se provoca algn evento.
<Canvas MouseLeftButtonDown="handler1" Width="100" Height="100">
<Ellipse Width="50" Height="50" Fill="Blue" Canvas.Left="30" Canvas.Top="50"
MouseLeftButtonDown="handler2"/>
</Canvas>
Cuando se presiona el botn primario del mouse sobre la elipse, se ejecuta handler2. Cuando finaliza handler2,
el evento se pasa al objeto Canvas, que utiliza handler1 para procesarlo. Esto solamente pasa si handler2 no
marca explcitamente el objeto de evento como administrado.
Es posible que handler2 tarde mucho tiempo en procesar este evento. handler2 podra utilizar PushFrame para
iniciar un bucle de mensajes anidado que no volviera durante horas. Si handler2 no marca el evento como
administrado cuando finaliza este bucle de mensajes, el evento se pasa al rbol aunque sea muy antiguo.
Volver a entrar y bloqueo
El mecanismo de bloqueo de common language runtime (CLR) no se comporta exactamente como se podra
imaginar; podra esperarse que un subproceso cesara completamente de funcionar al solicitar un bloqueo. En
realidad, el subproceso contina recibiendo y procesando mensajes de alta prioridad. Esto ayuda a evitar
interbloqueos y minimiza la sensibilidad de las interfaces, pero introduce la posibilidad de errores sutiles.
Durante la mayor parte del tiempo no necesitar saber nada sobre esto pero, en raras circunstancias (que
habitualmente implican mensajes de ventanas de Win32 o componentes COM STA) puede merecer la pena
conocer este tema.
La mayora de las interfaces no se han creado pensando en la seguridad de los subprocesos, porque los
programadores trabajan partiendo del supuesto de que nunca habr ms de un subproceso con acceso a la
interfaz de usuario. En este caso, ese subproceso nico puede modificar el entorno en momentos inesperados,
efectos
indeseables
que
el
mecanismo
de
exclusin
mutua
de
DispatcherObject
debe
La mayor parte del tiempo es correcto, pero hay momentos en WPF en los que tal vuelta a entrar inesperada
realmente puede causar problemas. Por lo tanto, en ciertos momentos clave, WPF llama a DisableProcessing,
que cambia la instruccin de bloqueo para que ese subproceso utilice el bloqueo sin vuelta a entrar de WPF, en
lugar del bloqueo CLRhabitual.
Entonces, por qu el equipo de CLR eligi este comportamiento? Tena que ver con los objetos COM STA y el
subproceso de finalizacin. Cuando un objeto se somete a la recopilacin de elementos no utilizados, su mtodo
Finalize se ejecuta en el subproceso finalizador dedicado, no en el subproceso de la interfaz de usuario. Ah
reside el problema, porque un objeto COM STA creado en el subproceso de la interfaz de usuario slo se puede
desechar en el subproceso de la interfaz de usuario. CLR realiza el equivalente de BeginInvoke) (en este caso
utilizando el mtodo SendMessage de Win32. Sin embargo, si el subproceso de la interfaz de usuario est
ocupado, el subproceso finalizador se atasca y no se puede desechar el objeto COM STA, lo que crea una grave
prdida de memoria. En consecuencia, el equipo de CLR tom esta decisin para que los bloqueos funcionaran
como lo hacen.
La tarea de WPF es evitar que se vuelva a entrar de forma inesperada sin reintroducir la prdida de memoria,
que es el motivo por el que no bloqueamos la vuelta a entrar en todas partes.