Вы находитесь на странице: 1из 84

Contraer todo Código: Todos

Windows Presentation Foundation


Introducción a Windows Presentation Foundation
Vea también Enviar comentarios

Windows Presentation Foundation (WPF) es un sistema de presentación de la próxima generación, para crear aplicaciones cliente de Windows
que proporcionen una experiencia impactante para el usuario desde el punto de vista visual. Con WPF, puede crear una amplia gama de
aplicaciones independientes y hospedadas en explorador. Algunos ejemplos de ello son Yahoo! Messenger y New York Times Reader, así como la
aplicación de ejemplo para atención sanitaria, Contoso Healthcare Sample Application que se muestra en la ilustración siguiente.

El núcleo de WPF es un motor de representación independiente de la resolución y basado en vectores construido para aprovechar al máximo el
hardware de gráficos moderno. WPF amplía el núcleo con un completo conjunto de características de programación de aplicaciones, entre las que
se incluyen Lenguaje de marcado de aplicaciones extensible (XAML), controles, enlaces de datos, diseño, gráficos 2D y 3D, animación, estilos,
plantillas, documentos, multimedia, texto y tipografía. WPF se incluye en Microsoft .NET Framework, lo que permite crear aplicaciones que
incorporen otros elementos de la biblioteca de clases de .NET Framework.

Esta introducción está dirigida a personas que no conocen aún WPF, y en ella se abordan sus conceptos y capacidades principales. Los
programadores de WPF experimentados que deseen revisar este marco de trabajo también la encontrarán de utilidad.

Nota:
Para conocer las características nuevas y actualizadas de WPF en .NET Framework 3.5, vea Lo nuevo en Windows Presentation Foundation
versión 3.5.

Este tema contiene las secciones siguientes.


 Programar con WPF
 Código de lenguaje marcado y código subyacente

 Aplicaciones
 Controles

 Acciones del usuario y comandos


 Diseño
 Enlace de datos
 Gráficos

 Animación
 Multimedia
 Texto y tipografía
 Documentos
 Personalizar las aplicaciones WPF

 Procedimientos recomendados en WPF


 Resumen

 Introducciones y ejemplos recomendados


 Temas relacionados

Programar con WPF

WPF constituye un subconjunto de tipos de .NET Framework, en su mayoría contenidos en el espacio de nombres de System.Windows. Si
ha creado previamente aplicaciones con .NET Framework mediante tecnologías administradas como ASP.NET y formularios Windows Forms,
los conceptos fundamentales de la programación en WPF deben resultarle familiares; creará instancias de clases, definirá propiedades,
llamará a métodos y controlará eventos con el lenguaje de programación de .NET Framework que prefiera, como C# o Visual Basic.

Para admitir algunas de las funciones de WPF más eficaces y simplificar la experiencia de programación, WPF incluye construcciones de
programación adicionales que mejoran las propiedades y los eventos: las propiedades de dependencia y los eventos enrutados. Para
obtener más información acerca de las propiedades de dependencia, vea Información general sobre las propiedades de dependencia. Para
obtener más información acerca de los eventos enrutados, vea Información general sobre eventos enrutados.

Código de lenguaje marcado y código subyacente

WPF proporciona mejoras de programación adicionales para el desarrollo de aplicaciones cliente de Windows. Una mejora evidente es la
capacidad para programar una aplicación mediante código de lenguaje marcado y subyacente, una experiencia con la que resultará familiar
a los programadores de ASP.NET. En general, se utiliza el lenguaje marcado Lenguaje de marcado de aplicaciones extensible (XAML) para
implementar la apariencia de una aplicación, y los lenguajes de programación administrados (subyacentes) para implementar su
comportamiento. Esta separación entre la apariencia y el comportamiento aporta las ventajas siguientes:
 Se reducen los costos de programación y mantenimiento, al no estar el marcado específico de la apariencia estrechamente relacionado
con el código específico del comportamiento.
 La programación es más eficaz porque los diseñadores pueden implementar la apariencia de una aplicación al mismo tiempo que los
programadores implementan su comportamiento.
 Se pueden utilizar varias herramientas de diseño para implementar y compartir el lenguaje marcado XAML, a fin de responder a los
requisitos de los colaboradores de programación de aplicaciones; Microsoft Expression Blend proporciona una experiencia apropiada
para los diseñadores, mientras que Visual Studio 2005 está dirigido a los programadores.
 La globalización y localización de las aplicaciones WPF se ha simplificado en gran medida (vea Información general sobre la localización
y globalización de WPF).

A continuación, se muestra una introducción breve al código de lenguaje marcado y subyacente de WPF. Para obtener más información
acerca de este modelo de programación, vea Información general sobre XAML y Código subyacente y XAML.

Marcado
XAML es un lenguaje de marcado basado en XML que se utiliza para implementar la apariencia de una aplicación mediante declaración. Se
suele utilizar para crear ventanas, cuadros de diálogo, páginas y controles de usuario, así como para rellenarlos con controles, formas y
gráficos.

En el ejemplo siguiente se utiliza XAML para implementar la apariencia de una ventana que contiene un solo botón.

XAML Copiar código

<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 código XAML define una ventana y un botón 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 título de la ventana. En
tiempo de ejecución, 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 ilustración siguiente se muestra la interfaz de usuario (UI) definida mediante el código XAML del ejemplo anterior.

Para obtener más información, vea Información general sobre XAML.

Puesto que XAML se basa en XML, la interfaz de usuario que se crea con este lenguaje se ensambla en una jerarquía de elementos anidados
que se denomina árbol de elementos. El árbol de elementos proporciona una manera lógica e intuitiva de crear y administrar las UIs. Para
obtener más información, vea Árboles en WPF.

Código subyacente
El comportamiento principal de una aplicación es implementar la funcionalidad que responde a las interacciones con el usuario, lo que
incluye controlar los eventos (por ejemplo, hacer clic en un menú, una barra de herramientas o un botón) y llamar, en respuesta, a la lógica
empresarial y de acceso a los datos. En WPF, este comportamiento se suele implementar en código asociado al marcado. Este tipo de
código se denomina subyacente. En el ejemplo siguiente se muestran el código subyacente y el marcado actualizado del ejemplo anterior.

XAML Copiar código

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.AWindow"
Title="Window with Button"
Width="250" Height="100">

<!-- Add button to window -->


<Button Name="button" Click="button_Click">Click Me!</Button>
</Window>

C# Copiar código

using System.Windows; // Window, RoutedEventArgs, MessageBox

namespace SDKSample
{
public partial class AWindow : Window
{
public AWindow()
{
// InitializeComponent call is required to merge the UI
// that is defined in markup with this class, including
// setting properties and registering event handlers
InitializeComponent();
}

void button_Click(object sender, RoutedEventArgs e)


{
// Show message box when button is clicked
MessageBox.Show("Hello, Windows Presentation Foundation!");
}
}
}

Visual Basic Copiar código

Namespace SDKSample

Partial Public Class AWindow


Inherits System.Windows.Window

Public Sub New()

' InitializeComponent call is required to merge the UI


' that is defined in markup with this class, including
' setting properties and registering event handlers
InitializeComponent()

End Sub

Sub button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)

' Show message box when button is clicked


MessageBox.Show("Hello, Windows Presentation Foundation!")

End Sub

End Class

End Namespace

En este ejemplo, el código subyacente implementa una clase que se deriva de la clase Window. El atributo x:Class se utiliza para asociar el
marcado a la clase de código subyacente. Se llama a InitializeComponent desde el constructor de la clase de código subyacente para
combinar la interfaz de usuario definida en el marcado con la clase de código subyacente. ((InitializeComponent se genera
automáticamente al generar la aplicación, por lo que no se requiere su implementación manual.) La combinación de x:Class e
InitializeComponent garantiza que la implementación se inicializa correctamente cada vez que se crea. La clase de código subyacente
también implementa un controlador de eventos para el evento Click del botón. Cuando se hace clic en el botón, el controlador de eventos
muestra un cuadro de mensaje llamando al método MessageBox.Show.

En la ilustración siguiente se muestra el resultado de hacer clic en el botón.

Para obtener más información, vea Código subyacente y XAML.

Aplicaciones

.NET Framework, System.Windows, así como el código de lenguaje marcado y subyacente, constituyen la base de la experiencia de
programación de aplicaciones en WPF. Además, WPF cuenta con características 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 aplicación. El modelo de aplicación admite la programación de aplicaciones independientes y
hospedadas en explorador.

Aplicaciones independientes
Para las aplicaciones independientes, puede utilizar la clase Window para crear las ventanas y cuadros de diálogo a los que se tiene acceso
desde las barras de menús y las barras de herramientas. En la ilustración siguiente se muestra una aplicación independiente con una
ventana principal y un cuadro de diálogo.

Además, puede utilizar los cuadros de diálogo siguientes de WPF: MessageBox, OpenFileDialog, SaveFileDialog y PrintDialog.

Para obtener más información, vea Información general sobre ventanas de WPF.

Aplicaciones hospedadas en explorador


Para las aplicaciones hospedadas en explorador, denominadas Aplicaciones del explorador XAML (XBAPs), puede crear páginas (Page) y
funciones de página (PageFunction(T)) entre las que se puede navegar mediante hipervínculos (clases Hyperlink). En la ilustración siguiente
se muestra una página de XBAP hospedada en Internet Explorer 7.
Las aplicaciones WPF se pueden hospedar en Internet Explorer 7 y Internet Explorer 7. WPF proporciona las dos opciones siguientes de
hosts de navegación alternativos:
 Frame, para hospedar islas de contenido navegable en páginas o ventanas.
 NavigationWindow, para hospedar contenido navegable en una ventana completa.

Para obtener más información, vea Información general sobre navegación.

Clase Application
Tanto las XBAPs como las aplicaciones independientes suelen presentar la complejidad suficiente para necesitar servicios adicionales de
ámbito de la aplicación, lo que incluye administración del inicio y de la duración, así como las propiedades y los recursos compartidos. La
clase Application incluye todos estos servicios y más, y se puede implementar sólo mediante XAML, como se muestra en el ejemplo
siguiente.

XAML Copiar código

<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />

Este código de lenguaje marcado es la definición de aplicación de una aplicación independiente, e indica a WPF que cree un objeto
Application que abre MainWindow automáticamente cuando se inicia la aplicación.

Un concepto que es fundamental entender acerca de Application es que proporciona una plataforma común de compatibilidad para las
aplicaciones independientes y hospedadas en explorador. Por ejemplo, el código XAML anterior podría utilizarlo una aplicación hospedada en
explorador para navegar automáticamente a una página al iniciar una XBAP, como se muestra en el ejemplo siguiente.

XAML Copiar código

<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml" />

Para obtener más información, vea Información general sobre la administración de aplicaciones.

Seguridad
Dado que las XBAPs se hospedan en un explorador, la seguridad es importante. En particular, las XBAPs utilizan un recinto de seguridad de
confianza parcial para aplicar restricciones menores o iguales a las que se imponen a las aplicaciones basadas en HTML. Además, todas las
características de HTML que es seguro ejecutar desde las XBAPs con confianza parcial se han probado mediante un proceso de seguridad
completo, que se detalla en Estrategia de seguridad de Windows Presentation Foundation: Ingeniería de seguridad.

Aún así, la mayoría de las características de WPF se pueden ejecutar con seguridad desde las XBAPs, como se describe en Seguridad de
confianza parcial en Windows Presentation Foundation.

Controles

Las experiencias para el usuario proporcionadas por el modelo de aplicación son controles construidos. En WPF, un "control" es un término
general que se aplica a una categoría de clases de WPF hospedadas en una ventana o una página, tienen una interfaz de usuario (UI) e
implementa un comportamiento determinado.

Para obtener más información, vea Información general sobre controles. Para ver ejemplos de introducción, vea Ejemplos de Control
Library.

Lista controles de WPF


A continuación se muestra la lista de controles de WPF integrados.
 Botones: Button y RepeatButton.
 Cuadros de diálogo: OpenFileDialog, PrintDialog y SaveFileDialog.

 Entradas manuscritas digitales: InkCanvas y InkPresenter.


 Documentos: DocumentViewer, FlowDocumentPageViewer, FlowDocumentReader, FlowDocumentScrollViewer y StickyNoteControl.
 Entrada: TextBox, RichTextBox y PasswordBox.
 Diseño: Border, BulletDecorator, Canvas, DockPanel, Expander, Grid, GridView, GridSplitter, GroupBox, Panel, ResizeGrip, Separator,
ScrollBar, ScrollViewer, StackPanel, Thumb, Viewbox, VirtualizingStackPanel, Window y WrapPanel.
 Multimedia: Image, MediaElement y SoundPlayerAction.
 Menús: ContextMenu, Menu y ToolBar.
 Navegación: Frame, Hyperlink, Page, NavigationWindow y TabControl.
 Selección: CheckBox, ComboBox, ListBox, TreeView y RadioButton, Slider.
 Información para el usuario: AccessText, Label, Popup, ProgressBar, StatusBar, TextBlock y ToolTip.

Acciones del usuario y comandos

Los controles casi siempre detectan las acciones del usuario y responden a ellas. El sistema de entrada de WPF utiliza eventos directos y
enrutados para admitir entradas de texto, la administración del enfoque y la posición del mouse. Para obtener más información, vea
Información general sobre acciones del usuario.

Las aplicaciones suelen tener requisitos de entrada complejos. WPF proporciona un sistema de comandos que separa las acciones de
entrada del usuario del código que responde a esas acciones. Para obtener más información, vea Información general sobre comandos.

Diseño

Al crear una interfaz de usuario, se organizan los controles según su ubicación y tamaño para crear un diseño. Un requisito fundamental de
cualquier diseño es adaptarse a los cambios de tamaño de la ventana y de configuración de pantalla. En lugar de obligarle a escribir código
que adapte el diseño en estas circunstancias, WPF le proporciona un sistema de diseño extensible de primera clase.

La piedra angular del sistema de diseño es la situación relativa, que aumenta la capacidad de adaptación a los cambios en la configuración
de las ventanas y de la pantalla. Además, el sistema de diseño administra la negociación entre los controles para determinar el diseño. La
negociación es un proceso de dos pasos: en primer lugar, el control indica a su elemento primario qué ubicación y tamaño necesita; en
segundo lugar, el elemento primario indica al control de qué espacio dispone.

El sistema de diseño se expone a los controles secundarios mediante las clases base de WPF. Para los diseños comunes, como son las
cuadrículas, el apilamiento y el acoplamiento, WPF incluye varios controles de diseño:
 Canvas: los controles secundarios proporcionan su propio diseño.
 DockPanel: los controles secundarios se alinean con los bordes del panel.
 Grid: los controles secundarios se sitúan por filas y columnas.

 StackPanel: los controles secundarios se apilan vertical u horizontalmente.

 VirtualizingStackPanel: los controles secundarios se organizan en una vista "virtual" de una sola línea en sentido horizontal o vertical.
 WrapPanel: los controles secundarios se sitúan por orden de izquierda a derecha y se ajustan a la línea siguiente cuando hay más
controles de los que caben en la línea actual.

En el ejemplo siguiente se utiliza un control DockPanel para situar varios controles TextBox.

XAML Copiar código

<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 cómo 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 construcción de
WPF denominada propiedad asociada (vea Información general sobre propiedades asociadas).

En la ilustración siguiente se muestra el resultado del marcado XAML del ejemplo anterior.

Para obtener más información, vea Sistema de diseño. Para ver un ejemplo de introducción, vea Ejemplo WPF Layout Gallery.

Enlace de datos

La mayoría 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 tecnologías existentes, como Microsoft SQL Server y
ADO.NET. Después de obtener acceso a los datos y de cargarlos a los objetos administrados de una aplicación, 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.

Para simplificar la programación de aplicaciones, WPF proporciona un motor de enlace de datos que realiza estos pasos
automáticamente. La unidad que constituye el núcleo del motor de enlace de datos es la clase Binding, encargada de enlazar un control (el
destino del enlace) a un objeto de datos (el origen del enlace). Esta relación se muestra en la ilustración siguiente.

En el ejemplo siguiente se muestra cómo enlazar un control TextBox a una instancia de un objeto Person personalizado. La implementación
de Person se muestra en el código siguiente.

C# Copiar código

namespace SDKSample
{
class Person
{
string name = "No Name";

public string Name


{
get { return name; }
set { name = value; }
}
}
}

Visual Basic Copiar código

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.

XAML Copiar código

<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>

C# Copiar código

using System.Windows; // Window

namespace SDKSample
{
public partial class DataBindingWindow : Window
{
public DataBindingWindow()
{
InitializeComponent();

// Create Person data source


Person person = new Person();

// Make data source available for binding


this.DataContext = person;
}
}
}

Visual Basic Copiar código

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 código 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 código 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 validación, ordenación, filtrado y agrupación. Además,
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 estándar de WPF no es adecuada.

Para obtener más información, vea Información general sobre el enlace de datos. Para ver un ejemplo de introducción, vea Demo Data
Binding.

Gráficos

WPF presenta un conjunto extenso, escalable y flexible de características de gráficos que aportan las ventajas siguientes:
 Gráficos independientes de la resolución e independientes del dispositivo. La unidad de medida básica del sistema de gráficos
de WPF es el píxel independiente del dispositivo, que es 1/96 de pulgada, independientemente de la resolución de pantalla real, y que
proporciona la base para la representación independiente de la resolución y del dispositivo. Cada píxel independiente del dispositivo se
escala automáticamente para coincidir con el valor de puntos por pulgada (ppp) del sistema en que se representa.
 Precisión mejorada. El sistema de coordenadas de WPF se mide con números de punto flotante de precisión doble, en lugar de
precisión simple. Las transformaciones y los valores de opacidad también se expresan como doble precisión. WPF admite también una
amplia gama de colores (scRGB) y proporciona compatibilidad integrada para administrar las entradas desde espacios de color
diferentes.
 Compatibilidad con gráficos avanzados y animación. WPF simplifica la programación de gráficos administrando automáticamente
las escenas de animación; no tendrá que preocuparse por el procesamiento de escenas, los bucles de representación ni la interpolación
bilineal. Además, WPF admite la comprobación de clics y proporciona compatibilidad plena con la composición alfa.
 Aceleración de hardware. El sistema de gráficos de WPF saca partido del hardware de gráficos para minimizar el uso de la CPU.

Formas 2D
WPF proporciona una biblioteca de formas 2D comunes dibujadas mediante vectores, como los rectángulos y las elipses que se muestran en
la ilustración siguiente.

Una función interesante de las formas es que no sirven únicamente para su presentación; las formas implementan muchas de las
características 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.

XAML Copiar código

<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>

C# Copiar código

using System.Windows; // Window, MessageBox


using System.Windows.Input; // MouseButtonEventHandler

namespace SDKSample
{
public partial class EllipseEventHandlingWindow : Window
{
public EllipseEventHandlingWindow()
{
InitializeComponent();
}

void clickableEllipse_MouseUp(object sender, MouseButtonEventArgs e)


{
// Display a message
MessageBox.Show("You clicked the ellipse!");
}
}
}

Visual Basic Copiar código

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 ilustración siguiente se muestra lo que el código anterior genera.

Para obtener más información, vea Información general sobre formas y dibujo básico en WPF. Para ver un ejemplo de introducción, vea
Ejemplo Shape Elements.

Geometrías 2D
Las formas 2D proporcionadas por WPF abarcan el conjunto estándar de formas básicas. Sin embargo, puede que sea preciso crear formas
personalizadas para facilitar el diseño de una interfaz de usuario personalizada. Para este fin, WPF proporciona las geometrías. En la
ilustración siguiente se muestra el uso de geometrías 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 comprobación de visitas y la representación de datos de gráficos 2D.

Para obtener más información, vea Información general sobre geometría. Para ver un ejemplo de introducción, vea Ejemplo Geometries.

Efectos 2D
Un subconjunto de las funciones 2D de WPF son los efectos visuales, tales como degradados, mapas de bits, dibujos, pintar con vídeos,
rotación, ajuste de escala y sesgo. Todas ellas se aplican mediante pinceles; en la siguiente ilustración se muestran algunos ejemplos.

Para obtener más información, vea Información general sobre pinceles de WPF. Para ver un ejemplo de introducción, vea Ejemplo Brushes.

Representación 3D
WPF también incluye funciones de representación 3D que se integran con los gráficos 2D para permitir la creación de UIs más interesantes
y apasionantes. Por ejemplo, en la ilustración siguiente se muestran imágenes 2D representadas en formas 3D.
Para obtener más información, vea Información general sobre gráficos 3D. Para ver un ejemplo de introducción, vea Ejemplo 3-D Solids.

Animación

La compatibilidad de WPF con la animación permite hacer que los controles crezcan, tiemblen, giren o se desvanezcan, crear transiciones de
página interesantes, y mucho más. Puede animar la mayoría de las clases de WPF, incluso las personalizadas. En la ilustración siguiente se
muestra una animación simple en acción.

Para obtener más información, vea Información general sobre animaciones. Para ver un ejemplo de introducción, vea Ejemplo Animation
Example Gallery.

Multimedia

Una manera de mostrar un contenido enriquecido es utilizar medios audiovisuales (multimedia). WPF proporciona compatibilidad especial
con imágenes, vídeo y audio.

Imágenes
Las imágenes están presentes en la mayoría de las aplicaciones y WPF proporciona varias maneras de utilizarlas. En la ilustración siguiente
se muestra una interfaz de usuario con un cuadro de lista que contiene imágenes en miniatura. Cuando se selecciona una miniatura,
aparece la imagen a tamaño completo.
Para obtener más información, vea Información general sobre imágenes. Para ver un ejemplo de introducción, vea Demo WPF Photo
Viewer.

Vídeo y audio
El control MediaElement es capaz de reproducir vídeo y audio y presenta la flexibilidad suficiente para constituir la base de un reproductor
multimedia personalizado. El marcado XAML siguiente implementa un reproductor multimedia.

XAML Copiar código

<MediaElement
Name="myMediaElement"
Source="media/wpf.wmv"
LoadedBehavior="Manual"
Width="350" Height="250" />

En la ventana de la ilustración siguiente se muestra el control MediaElement en acción.

Para obtener más información, vea Información general sobre características de gráficos, animación y multimedia en WPF. Para ver un
ejemplo de introducción, vea Ejemplo Media Gallery.

Texto y tipografía

Para facilitar una representación de texto de gran calidad, WPF ofrece las características siguientes:
 Compatibilidad con fuentes OpenType.
 Mejoras de ClearType.
 Alto rendimiento que saca partido de la aceleración de hardware.
 Integración de texto con multimedia, gráficos y animación.

 Compatibilidad con fuentes internacionales y mecanismos de reserva.

A modo de demostración de la integración del texto con gráficos, en la ilustración siguiente se muestra la aplicación de decoraciones al
texto.

Para obtener más información, vea Tipografía en Windows Presentation Foundation. Para ver ejemplos de introducción, vea Ejemplos de
tipografía.

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 también servicios para crear, ver, administrar, anotar, empaquetar e imprimir documentos.

Documentos dinámicos
Los documentos dinámicos se han diseñado para optimizar su presentación y legibilidad ajustando dinámicamente su contenido y
modificando su flujo cuando se producen cambios en el tamaño de la ventana y la configuración de pantalla. En el marcado XAML siguiente
se muestra la definición de FlowDocument.

XAML Copiar código

<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 cómo cargar un documento dinámico en FlowDocumentReader para leerlo, realizar búsquedas e
imprimirlo.

XAML Copiar código

<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>

C# Copiar código

using System.Windows; // Window


using System.Windows.Documents; // FlowDocument
using System.IO; // FileStream, FileMode
using System.Windows.Markup; // XamlReader

namespace SDKSample
{
public partial class FlowDocumentReaderWindow : System.Windows.Window
{
public FlowDocumentReaderWindow()
{
InitializeComponent();

// Open the file that contains the FlowDocument


using (FileStream xamlFile = new FileStream("AFlowDocument.xaml",
FileMode.Open, FileAccess.Read))
{
// Parse the file with the XamlReader.Load method
FlowDocument content = XamlReader.Load(xamlFile) as FlowDocument;

// Set the Document property to the parsed FlowDocument object


this.flowDocumentReader.Document = content;
}
}
}
}

Visual Basic Copiar código

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.

Para obtener más información, vea Información general sobre documentos dinámicos. Para ver un ejemplo de introducción, vea Ejemplo
FlowDocument Properties.

Documentos fijos
Los documentos fijos están destinados a aplicaciones que requieren una presentación con representación fiel (lo que se ve es lo que se
obtiene, o WYSIWYG, en sus siglas en inglés) precisa, especialmente por lo que respecta a su impresión. Los usos típicos para los
documentos fijos incluyen la creación de publicaciones, el procesamiento de textos y el diseño de formularios, donde es vital que se respete
el diseño de página original.

Los documentos fijos conservan la organización precisa de su contenido de una manera independiente del dispositivo. Por ejemplo, un
documento fijo mostrado en una pantalla de 96 puntos por pulgada (ppp) aparece exactamente igual que cuando se imprime en una
impresora láser de 600 ppp o una máquina tipográfica fotográfica de 4800 ppp. El diseño permanece inalterado en todos los casos, aunque
la calidad del documento varía según las funciones de cada dispositivo.

Para obtener más información, vea Documentos en Windows Presentation Foundation.

Documentos XPS
Los documentos de XML Paper Specification (XPS) se basan en documentos fijos de WPF. Los documentos de XPS se describen con un
esquema basado en XML que básicamente es una representación en forma de página de documentos electrónicos. XPS es un formato de
documento abierto habilitado para varios exploradores y diseñado para facilitar la creación, el uso compartido, la impresión y el
almacenamiento de documentos paginados. Entre las características importantes de la tecnología XPS se incluyen:
 Empaquetado de documentos XPS como archivos ZipPackage conformes con la especificación Open Packaging Conventions (OPC).

 Hospedaje en aplicaciones independientes y basadas en explorador.


 Generación y manipulación manuales de documentos XPS desde las aplicaciones WPF.
 Representación de gran fidelidad gracias al establecimiento como destino de la máxima calidad del dispositivo de salida.

 Puesta en cola para impresión de Windows Vista.


 Enrutamiento directo de documentos a impresoras compatibles con XPS.

 Integración de la interfaz de usuario con DocumentViewer.

En la ilustración siguiente se muestra un documento XPS mostrado en un control DocumentViewer.


DocumentViewer también permite a los usuarios cambiar la vista de los documentos XPS, realizar búsquedas en ellos e imprimirlos.

Para obtener más información, vea Documentos en Windows Presentation Foundation. Para ver un ejemplo de introducción, vea Ejemplo
Creating an XPS Document.

Anotaciones
Las anotaciones son notas o comentarios que se agregan a los documentos para marcar la información o resaltar elementos de interés, a fin
de consultarlos más adelante. Aunque escribir notas en documentos impresos es fácil, la posibilidad de "escribir" notas en los documentos
electrónicos con frecuencia es limitada o no está disponible en absoluto. Sin embargo, en WPF se proporciona un sistema de anotaciones
que admite la inserción de notas rápidas y el resaltado. Además, estas anotaciones se pueden aplicar a documentos hospedados en el
control DocumentViewer, como se muestra en la ilustración siguiente.

Para obtener más información, vea Información general sobre anotaciones. Para ver un ejemplo de introducción, vea Ejemplo Document
Serialization.

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 portátil, sencillo de distribuir y de fácil 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. También puede cifrar los paquetes mediante la administración
de derechos para restringir el acceso a la información protegida.

Para obtener más información, vea Documentos en Windows Presentation Foundation. Para ver ejemplos, vea Ejemplos de empaquetado.

Impresión
.NET Framework incluye un subsistema de impresión al que WPF aporta, además, compatibilidad con el control de sistemas de impresión
mejorados. Las mejoras de impresión incluyen las siguientes:
 Instalación en tiempo real de servidores de impresión y colas remotos.

 Detección dinámica de funciones de impresora.


 Configuración dinámica de opciones de impresión.
 Modificación del enrutamiento y las prioridades de los trabajos de impresión.

Los documentos XPS presenta, además, una mejora fundamental del rendimiento. La ruta de acceso de Interfaz de dispositivo gráfico de
Microsoft Windows (GDI) de impresión suele requerir dos conversiones:
 La primera conversión del documento a un formato de procesador de impresión, como Metarchivo mejorado (EMF).
 Una segunda conversión al lenguaje de descripción de páginas 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 impresión y un lenguaje de descripción de páginas. Esta compatibilidad ayuda a reducir tamaño del archivo de cola y las
cargas de las impresoras integradas en red.

Para obtener más información, vea Información general sobre impresión. Para ver un ejemplo de introducción, vea Printing an XPS
Document.

Personalizar las aplicaciones WPF


Hasta este punto, hemos estudiado las unidades de creación de WPF fundamentales para la programación de aplicaciones. El modelo de
aplicación se utiliza para hospedar y distribuir el contenido de las aplicaciones, que está compuesto principalmente de controles. Para
simplificar la organización de los controles en una interfaz de usuario y asegurarse de que la organización se conserve aunque se
modifiquen el tamaño de la ventana y la configuración de pantalla, se utiliza el sistema de diseño de WPF. Dado que la mayor parte de las
aplicaciones permiten a los usuarios interactuar con los datos, los enlaces de datos se utilizan para reducir el trabajo de integración de la
interfaz de usuario con esos datos. A fin de mejorar la apariencia visual de la aplicación, se utiliza toda la gama de gráficos, animación y
multimedia que WPF admite. Por último, si la aplicación funciona a través de texto y documentos, puede utilizar las funciones de tipografía,
documentos, anotación, empaquetado e impresión 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 aplicación. Es posible
que los datos no se muestren del modo más 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 aplicación. En muchos aspectos, una tecnología de
presentación requiere la extensibilidad visual tanto como cualquier otro tipo de extensibilidad.

Por esta razón, WPF proporciona gran variedad de mecanismos para la creación de experiencias de usuario únicas, incluido un modelo de
contenido enriquecido para los controles, desencadenadores, plantillas de controles y datos, estilos, recursos de la interfaz de usuario,
temas y máscaras.

Modelo de contenido
El propósito principal de la mayoría de los controles de WPF es mostrar contenido. En WPF, el tipo y número de elementos que pueden
constituir el contenido de un control se denomina el modelo de contenido del control. Algunos controles pueden contener un solo elemento
y tipo de contenido; por ejemplo, el contenido de un control TextBox es un valor de tipo String que está asignado a la propiedad Text. En el
ejemplo siguiente se establece el contenido de TextBox.

XAML Copiar código

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.TextBoxContentWindow"
Title="TextBox Content">

...

<TextBox Text="This is the content of a TextBox." />

...

</Window>

En la ilustración siguiente se muestra el resultado.

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 diseño, texto,
imágenes y formas. En el ejemplo siguiente se muestra un control Button con contenido que incluye DockPanel, Label, Border y
MediaElement.

XAML Copiar código

<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 ilustración siguiente se muestra el contenido de este botón.


Para obtener más información sobre los tipos de contenido admitidos por los diversos controles, vea Modelo de contenido de WPF.

Desencadenadores
Aunque el propósito principal del marcado XAML es implementar la apariencia de una aplicación, también puede utilizar XAML para
implementar algunos aspectos del comportamiento de una aplicación. Un ejemplo de ello es el uso de desencadenadores para cambiar la
apariencia de una aplicación de acuerdo con las interacciones con el usuario. Para obtener más información, vea "Desencadenadores" en
Aplicar estilos y plantillas.

Plantillas de control
Las UIs predeterminadas para los controles de WPF suelen construirse a partir de otros controles y formas. Por ejemplo, un control Button
está compuesto de los controles ButtonChrome y ContentPresenter. ButtonChrome proporciona la apariencia del botón estándar, mientras
que ContentPresenter muestra el contenido del botón, especificado por la propiedad Content.

A veces, la apariencia predeterminada de un control puede ser incongruente con la apariencia global de una aplicación. En este caso, puede
utilizar una plantilla de control ControlTemplate para cambiar la apariencia de la interfaz de usuario del control sin modificar su contenido ni
su comportamiento.

En el ejemplo siguiente se muestra cómo cambiar la apariencia de un control Button mediante ControlTemplate.

XAML Copiar código

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.ControlTemplateButtonWindow"
Title="Button with Control Template" Height="158" Width="290">

<!-- Button using an ellipse -->


<Button Content="Click Me!" Click="button_Click">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Margin="5">
<Ellipse Stroke="DarkBlue" StrokeThickness="2">
<Ellipse.Fill>
<RadialGradientBrush Center="0.3,0.2" RadiusX="0.5" RadiusY="0.5">
<GradientStop Color="Azure" Offset="0.1" />
<GradientStop Color="CornflowerBlue" Offset="1.1" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter Name="content" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>

</Button>

</Window>

C# Copiar código

using System.Windows; // Window, RoutedEventArgs, MessageBox

namespace SDKSample
{
public partial class ControlTemplateButtonWindow : Window
{
public ControlTemplateButtonWindow()
{
InitializeComponent();
}

void button_Click(object sender, RoutedEventArgs e)


{
// Show message box when button is clicked
MessageBox.Show("Hello, Windows Presentation Foundation!");
}
}
}

Visual Basic Copiar código

Imports System.Windows ' Window, RoutedEventArgs, MessageBox

Namespace SDKSample

Public Class ControlTemplateButtonWindow


Inherits Window

Public Sub New()

InitializeComponent()

End Sub

Private Sub button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)


MessageBox.Show("Hello, Windows Presentation Foundation!")
End Sub

End Class

End Namespace

En este ejemplo, la interfaz de usuario del botón predeterminado se ha reemplazado por una forma Ellipse que tiene un borde azul marino y
se rellena mediante RadialGradientBrush. El control ContentPresenter muestra el contenido del control Button, "Click Me!" (¡Haga clic
aquí!). Al hacer clic en Button, se provoca como siempre el evento Click, que forma parte del comportamiento predeterminado del control
Button. El resultado se muestra en la ilustración siguiente.

Para obtener más información, vea ControlTemplate. Para ver un ejemplo de introducción, vea Ejemplo Styling with ControlTemplates.

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
ilustración siguiente se muestra la apariencia predeterminada de un control ListBox enlazado a una colección de objetos Task, donde cada
tarea tiene un nombre, descripción y prioridad.

La apariencia predeterminada es la que cabría 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 descripción y la prioridad, la apariencia predeterminada de
los elementos de lista enlazados al control ListBox se debe modificar, mediante DataTemplate. En el código XAML siguiente se define una
plantilla de datos DataTemplate, que se aplica a cada tarea mediante el atributo ItemTemplate.

XAML Copiar código

<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 ilustración siguiente se muestra el efecto de este código.

Observe que ListBox ha conservado su comportamiento y su apariencia global; únicamente ha cambiado la apariencia del contenido
mostrado por el cuadro de lista.

Para obtener más información, vea Información general sobre plantillas de datos. Para ver un ejemplo de introducción, vea Introducción al
ejemplo Data Templating.

Estilos
Los estilos permiten a los programadores y diseñadores normalizar un aspecto determinado de sus productos. WPF proporciona un modelo
de estilo sólido, que es la base del elemento Style. En el ejemplo siguiente se crea un estilo que establece el color de fondo de todos los
controles Button de una ventana en Orange.

XAML Copiar código

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.StyleWindow"
Title="Styles">

...

<!-- Style that will be applied to all buttons -->


<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Orange" />
<Setter Property="BorderBrush" Value="Crimson" />
<Setter Property="FontSize" Value="20" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Margin" Value="5" />
</Style>

...

<!-- This button will have the style applied to it -->


<Button>Click Me!</Button>

<!-- This labe will not have the style applied to it -->
<Label>Don't Click Me!</Label>

<!-- This button will have the style applied to it -->


<Button>Click Me!</Button>

...

</Window>

Dado que este estilo tiene como destino todos los controles Button, se aplica automáticamente a todos los botones de la ventana, como se
muestra en la ilustración siguiente.

Para obtener más información, vea Aplicar estilos y plantillas. Para ver un ejemplo de introducción, vea Ejemplo Introduction to Styling and
Templating.

Recursos
Los controles de una aplicación 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 ubicación única y poder reutilizarlos.

En el ejemplo siguiente se define un color de fondo común que es compartido por los controles Button y Label.

XAML Copiar código

<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. Un control individual (que utiliza la propiedad FrameworkElement.Resources heredada).
2. Window o Page (que también utiliza la propiedad FrameworkElement.Resources heredada).
3. Application (que utiliza la propiedad Application.Resources).
La variedad de ámbitos aporta flexibilidad al programador con respecto a la manera de definir y compartir los recursos.

Como alternativa a la asociación 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 una aplicación. En el ejemplo siguiente se define un
color de fondo predeterminado en un diccionario de recursos.

XAML Copiar código

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<!-- Define background color resource -->


<SolidColorBrush x:Key="defaultBackground" Color="Red" />

<!-- Define other resources -->

...

</ResourceDictionary>

En el ejemplo siguiente se hace referencia al diccionario de recursos definido en el ejemplo anterior para compartirlo en toda la aplicación.

XAML Copiar código

<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App">

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="BackgroundColorResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

...

</Application>

Los recursos y diccionarios de recursos constituyen el fundamento de la compatibilidad de WPF con los temas y las máscaras.

Para obtener más información, vea Información general sobre recursos. Para ver un ejemplo de introducción, vea Ejemplo Application
Resources.

Temas y máscaras
Desde una perspectiva visual, un tema define la apariencia global de Windows y de las aplicaciones que se ejecutan en su seno. Windows
incluye varios temas. Por ejemplo, Microsoft Windows XP se distribuye con los temas clásicos de Windows XP y Windows, mientras que
Windows Vista se distribuye con los temas clásicos de Windows Vista y Windows. La apariencia definida por un tema establece la apariencia
predeterminada de una aplicación WPF. Sin embargo, WPF no se integra directamente con los temas de Windows. Como el aspecto de WPF
se define mediante plantillas, WPF incluye una plantilla para cada uno de los temas conocidos de Windows, como Aero (Windows Vista),
Clásico (Microsoft Windows 2000), Luna (Microsoft Windows XP) y Royale (Microsoft Windows XP Media Center Edition 2005). Estos temas
están empaquetados en diccionarios de recursos que se resuelven cuando no se encuentran los recursos correspondientes en una
aplicación. Muchas aplicaciones se basan en estos temas para definir su apariencia visual; mantener la coherencia con la apariencia de
Windows ayuda a los usuarios a familiarizarse con las aplicaciones con mayor facilidad.

Por otro lado, la experiencia del usuario para algunas aplicaciones no procede necesariamente de los temas estándar. Por ejemplo,
Microsoft Windows Media Player funciona a través de datos de audio y vídeo y saca partido de un estilo diferente de experiencia del usuario.
Tales UIs tienden a proporcionar temas personalizados, específicos de cada aplicación. Se denominan máscaras, y las aplicaciones con
máscaras suelen proporcionar enlaces que permiten a los usuarios personalizar diversos aspectos de la máscara. Microsoft Windows Media
Player tiene varias máscaras prefabricadas, así como una serie de máscaras de otros fabricantes.

Tanto los temas como las máscaras de WPF se definen con toda facilidad mediante los diccionarios de recursos. En el ejemplo siguiente se
muestran ejemplos de definiciones de máscaras.

XAML Copiar código

<!-- Blue Skin -->


<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample">
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Blue" />
</Style>

...

<!-- Blue Skin -->


<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample">
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Blue" />
</Style>

...

</ResourceDictionary>

...

</ResourceDictionary>

XAML Copiar código

<!-- Yellow Skin -->


<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample">
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Yellow" />
</Style>

...

<!-- Yellow Skin -->


<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample">
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Yellow" />
</Style>

...

</ResourceDictionary>

...

</ResourceDictionary>

Para obtener más información, vea la sección sobre temas y recursos compartidos en Aplicar estilos y plantillas. Para ver un ejemplo de
introducción, vea Ejemplo Skinned Application.

Controles personalizados
Aunque WPF proporciona una amplísima compatibilidad con funciones de personalización, puede encontrar situaciones en que los controles
existentes de WPF no satisfagan las necesidades de la aplicación o de los usuarios. Esto puede suceder cuando:
 La interfaz de usuario que necesita no se puede crear personalizando la apariencia y el funcionamiento de las implementaciones de WPF
existentes.
 Las implementaciones de WPF existentes no admiten el comportamiento que se necesita (o lo admiten, pero no fácilmente).

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 continuación se
muestran los tres modelos:
 Modelo de control de usuario. El control personalizado se deriva de UserControl y se crea a partir de uno o varios controles.
 Modelo de control. El control personalizado se deriva de Control y se utiliza para generar implementaciones que separan su
comportamiento de su apariencia mediante plantillas, de un modo muy similar a la mayoría de los controles de WPF. Al derivarse de
Control, aporta mayor libertad para la creación de una interfaz de usuario personalizada que los controles de usuario, pero puede
requerir más esfuerzo.
 Modelo de elemento de marco de trabajo. Un control personalizado se deriva de FrameworkElement cuando su apariencia se define
mediante la lógica de representación personalizada (no mediante plantillas).

En el ejemplo siguiente se muestra un control numérico personalizado de arriba/abajo derivado de UserControl.

XAML Copiar código

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.NumericUpDown">
<Grid>

<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>

<!-- Value text box -->


<Border BorderThickness="1" BorderBrush="Gray" Margin="2" Grid.RowSpan="2"
VerticalAlignment="Center" HorizontalAlignment="Stretch">
<TextBlock Name="valueText" Width="60" TextAlignment="Right" Padding="5"/>
</Border>

<!-- Up/Down buttons -->


<RepeatButton Name="upButton" Click="upButton_Click" Grid.Column="1"
Grid.Row="0">Up</RepeatButton>
<RepeatButton Name="downButton" Click="downButton_Click" Grid.Column="1"
Grid.Row="1">Down</RepeatButton>

</Grid>

</UserControl>

C# Copiar código

using System; // EventArgs


using System.Windows; // DependencyObject, DependencyPropertyChangedEventArgs,
// FrameworkPropertyMetadata, PropertyChangedCallback,
// RoutedPropertyChangedEventArgs
using System.Windows.Controls; // UserControl

namespace SDKSample
{
public partial class NumericUpDown : UserControl
{
// NumericUpDown user control implementation

...

}
}

Visual Basic Copiar código

imports System 'EventArgs


imports System.Windows 'DependencyObject, DependencyPropertyChangedEventArgs,
' FrameworkPropertyMetadata, PropertyChangedCallback,
' RoutedPropertyChangedEventArgs
imports System.Windows.Controls 'UserControl

Namespace SDKSample

' Interaction logic for NumericUpDown.xaml


Partial Public Class NumericUpDown
Inherits System.Windows.Controls.UserControl

'NumericUpDown user control implementation

...

End Class

End Namespace

En el ejemplo siguiente se muestra el código XAML necesario para incorporar el control de usuario a una ventana (Window).

XAML Copiar código

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.UserControlWindow"
xmlns:local="clr-namespace:SDKSample"
Title="User Control Window">

...
<!-- Numeric Up/Down user control -->
<local:NumericUpDown />

...

</Window>

En la ilustración siguiente se muestra el control NumericUpDown hospedado en una ventana Window.

Para obtener más información sobre controles personalizados, vea Información general sobre la creación de controles. Para ver ejemplos de
introducción, vea Ejemplos de personalización de controles.

Procedimientos recomendados en WPF

Como sucede con cualquier plataforma de programación, 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 público en
general, existen procedimientos recomendados de accesibilidad, globalización y localización, y rendimiento. Para obtener más información,
vea las secciones siguientes:
 Procedimientos de accesibilidad recomendados
 Información general sobre la localización y globalización de WPF
 Optimizar WPF: Rendimiento de aplicaciones

 Seguridad de Windows Presentation Foundation

Resumen

WPF es una completa tecnología de presentación para generar gran variedad aplicaciones cliente impactantes desde el punto de vista
visual. En esta introducción se ha proporcionado una introducción general a las principales características de WPF.

El paso siguiente consiste en generar aplicaciones WPF.

Durante el proceso de creación, puede consultar de nuevo esta introducción para repasar las características clave y encontrar referencias a
artículos donde se abordan en mayor profundidad todas las características tratadas en esta introducción.

Introducciones y ejemplos recomendados

En esta introducción se mencionan las introducciones y los ejemplos siguientes.

Temas de introducción

Información general sobre gráficos 3D Información general sobre imágenes


Procedimientos de accesibilidad recomendados Información general sobre acciones del usuario
Información general sobre animaciones Sistema de diseño
Información general sobre anotaciones Información general sobre navegación
Información general sobre la administración de Información general sobre impresión
aplicaciones Información general sobre recursos
Información general sobre comandos Información general sobre eventos enrutados
Información general sobre la creación de controles Información general sobre formas y dibujo básico en WPF
Información general sobre controles Tipografía en Windows Presentation Foundation
Información general sobre el enlace de datos Seguridad de Windows Presentation Foundation
Información general sobre plantillas de datos Información general sobre ventanas de WPF
Información general sobre las propiedades de Información general sobre pinceles de WPF
dependencia
Modelo de contenido de WPF
Documentos en Windows Presentation Foundation
Información general sobre la localización y globalización de WPF
Árboles en WPF
Información general sobre características de gráficos, animación y multimedia
Información general sobre documentos dinámicos en WPF
Información general sobre geometría
Introducción a las entradas manuscritas

Ejemplos

Ejemplo 3-D Solids Introducción al ejemplo Data Templating


Ejemplos Accessibility Ejemplo Introduction to Styling and Templating
Ejemplo Animation Example Gallery Ejemplo Media Gallery
Ejemplo Application Resources Ejemplos de empaquetado
Ejemplo Brushes Printing an XPS Document
Ejemplos de personalización de controles Ejemplo Shape Elements
Ejemplos de Control Library Información general sobre formas y dibujo básico en WPF
Ejemplo Creating an XPS Document Ejemplo Skinned Application
Demo Data Binding Ejemplo Styling with ControlTemplates
Ejemplos de entrada manuscrita digital Ejemplos de tipografía
Ejemplo Document Serialization Ejemplo WPF Layout Gallery
Ejemplo FlowDocument Properties Demo WPF Photo Viewer
Ejemplo Geometries

Vea también
Conceptos
Información general sobre Windows Presentation Foundation
Comentarios de la comunidad de Windows Presentation Foundation

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
Button (Clase)
Miembros Ejemplo Vea también Enviar comentarios

Representa un control de botón de Windows, que reacciona al evento ButtonBase.Click.

Espacio de nombres: System.Windows.Controls


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: http://schemas.microsoft.com/winfx/xaml/presentation

Sintaxis

Visual Basic (Declaración)


Public Class Button _
Inherits ButtonBase

Visual Basic (Uso)


Dim instance As Button

C#
public class Button : ButtonBase

Visual C++
public ref class Button : public ButtonBase

J#
public class Button extends ButtonBase

JScript
public class Button extends ButtonBase

Uso de elementos de objeto XAML


<Button>
Content
</Button>

Comentarios

La clase Button hereda directamente de la clase System.Windows.Controls.Primitives.ButtonBase.

Modelo de contenido: El valor de Button es un objeto ContentControl. Su propiedad de contenido


es Content. Para obtener más información acerca del modelo de contenido de Button, vea
Información general sobre el modelo de contenido de controles.

Administre el evento ButtonBase.Click para responder cuando el usuario hace clic en Button.

El método OnMouseLeftButtonDown marca el evento MouseLeftButtonDown como administrado. Para


responder al evento MouseLeftButtonDown, asocie un controlador de eventos al evento
PreviewMouseLeftButtonDown o llame a AddHandler(RoutedEvent, Delegate, Boolean) con
handledEventsToo establecido en true.

Ejemplos

El ejemplo siguiente muestra tres botones que responden a los clics de tres maneras diferentes.
 Desplazar: el primer botón cambia de color cuando el usuario se desplaza con el mouse sobre el
botón.
 Presionar: el segundo botón requiere que se presione el mouse mientras el puntero del mouse está
encima del botón.
 Soltar: el tercero no restablece el color de fondo de los botones hasta que se presione el mouse y
se suelte el botón.

XAML Copiar código

<Button Name="btn1" Background="Pink"


BorderBrush="Black" BorderThickness="1"
Click="OnClick1" ClickMode="Hover">
ClickMe1
</Button>

<Button Name="btn2" Background="LightBlue"


BorderBrush="Black" BorderThickness="1"
Click="OnClick2" ClickMode="Press">
ClickMe2
</Button>

<Button Name="btn3"
Click="OnClick3" ClickMode="Release">
Reset
</Button>

C# Copiar código

void OnClick1(object sender, RoutedEventArgs e)


{
btn1.Background = Brushes.LightBlue;
}

void OnClick2(object sender, RoutedEventArgs e)


{
btn2.Background = Brushes.Pink;
}

void OnClick3(object sender, RoutedEventArgs e)


{
btn1.Background = Brushes.Pink;
btn2.Background = Brushes.LightBlue;
}

Visual Basic Copiar código

Private Sub OnClick1(ByVal sender As Object, ByVal e As RoutedEventArgs)


btn1.Background = Brushes.LightBlue
End Sub

Private Sub OnClick2(ByVal sender As Object, ByVal e As RoutedEventArgs)


btn2.Background = Brushes.Pink
End Sub

Private Sub OnClick3(ByVal sender As Object, ByVal e As RoutedEventArgs)


btn1.Background = Brushes.Pink
btn2.Background = Brushes.LightBlue
End Sub

Más código

Cómo: Crear un botón que En este ejemplo se muestra cómo incluir una imagen en un control
tenga una imagen Button.

Cómo: Crear un control que En este ejemplo se muestra cómo crear un control que tiene una
tenga tecla de acceso y tecla de acceso y admite el ajuste de texto. En el ejemplo se utiliza
ajuste de texto un control Label para ilustrar estos conceptos.
Jerarquía de herencia
System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.ContentControl
System.Windows.Controls.Primitives.ButtonBase
System.Windows.Controls.Button

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la
ejecución de subprocesos. No se garantiza que los miembros de instancias sean seguros para la
ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para
obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Conceptos
Ejemplo WPF Controls Gallery
Button Samples
Información general sobre controles
Biblioteca de controles

Referencia
Button (Miembros)
System.Windows.Controls (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
RepeatButton (Clase)
Miembros Ejemplo Vea también Enviar comentarios

Representa un control que provoca su evento Click de forma repetida desde el momento en que se presiona
hasta que se suelta.

Espacio de nombres: System.Windows.Controls.Primitives


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: http://schemas.microsoft.com/winfx/xaml/presentation

Sintaxis

Visual Basic (Declaración)


Public Class RepeatButton _
Inherits ButtonBase

Visual Basic (Uso)


Dim instance As RepeatButton

C#
public class RepeatButton : ButtonBase

Visual C++
public ref class RepeatButton : public ButtonBase

J#
public class RepeatButton extends ButtonBase

JScript
public class RepeatButton extends ButtonBase

Uso de elementos de objeto XAML


<RepeatButton>
Content
</RepeatButton>

Comentarios

Modelo de contenido: El valor de RepeatButton es un objeto ContentControl. Su propiedad de


contenido es Content. Para obtener más información acerca del modelo de contenido de
RepeatButton, vea Información general sobre el modelo de contenido de controles.

La clase RepeatButton que representa un control que es similar a Button. Sin embargo, los botones
repetidos le proporcionan control sobre cuándo y cómo se produce el evento Click. RepeatButton
provoca el evento Click de forma repetida desde el momento en que se presiona hasta que se suelta.
La propiedad Delay determina cuándo comienza el evento. También puede controlar el intervalo de las
repeticiones con la propiedad Interval.

Ejemplos

En el siguiente ejemplo se muestra cómo crear un RepeatButton.

XAML Copiar código

<RepeatButton Width="100" DockPanel.Dock="Top"


Delay="500" Interval="100"
Click="Increase">
Increase
</RepeatButton>

<TextBlock Name="valueText"
Width="100" DockPanel.Dock="Top"
TextAlignment="Center" FontSize="16">
0
</TextBlock>

<RepeatButton Width="100" DockPanel.Dock="Top"


Delay="500" Interval="100"
Click="Decrease">
Decrease
</RepeatButton>

C# Copiar código

void Increase(object sender, RoutedEventArgs e)


{
Int32 Num = Convert.ToInt32(valueText.Text);

valueText.Text = ((Num + 1).ToString());


}

void Decrease(object sender, RoutedEventArgs e)


{
Int32 Num = Convert.ToInt32(valueText.Text);

valueText.Text = ((Num - 1).ToString());


}

Visual Basic Copiar código

Sub Increase(ByVal sender As Object, ByVal e As RoutedEventArgs)

Num = CInt(valueText.Text)

valueText.Text = ((Num + 1).ToString())


End Sub

Sub Decrease(ByVal sender As Object, ByVal e As RoutedEventArgs)

Num = CInt(valueText.Text)

valueText.Text = ((Num - 1).ToString())


End Sub

Jerarquía de herencia
System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.ContentControl
System.Windows.Controls.Primitives.ButtonBase
System.Windows.Controls.Primitives.RepeatButton

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la
ejecución de subprocesos. No se garantiza que los miembros de instancias sean seguros para la
ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para
obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Referencia
RepeatButton (Miembros)
System.Windows.Controls.Primitives (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
OpenFileDialog (Clase)
Miembros Vea también Enviar comentarios

Representa un cuadro de diálogo común que permite al usuario especificar un nombre de archivo para abrir
uno o varios archivos.

Espacio de nombres: Microsoft.Win32


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: No asignado a un xmlns.

Sintaxis

Visual Basic (Declaración)


Public NotInheritable Class OpenFileDialog _
Inherits FileDialog

Visual Basic (Uso)


Dim instance As OpenFileDialog

C#
public sealed class OpenFileDialog : FileDialog

Visual C++
public ref class OpenFileDialog sealed : public FileDialog

J#
public final class OpenFileDialog extends FileDialog

JScript
public final class OpenFileDialog extends FileDialog

Uso de elementos de objeto XAML


<OpenFileDialog .../>

Jerarquía de herencia
System.Object
Microsoft.Win32.CommonDialog
Microsoft.Win32.FileDialog
Microsoft.Win32.OpenFileDialog

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la
ejecución de subprocesos. No se garantiza que los miembros de instancias sean seguros para la
ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para
obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Referencia
OpenFileDialog (Miembros)
Microsoft.Win32 (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
PrintDialog (Clase)
Miembros Ejemplo Vea también Enviar comentarios

Invoca un cuadro de diálogo de impresión de Microsoft Windows estándar que configura PrintTicket y PrintQueue según los datos
proporcionados por el usuario e imprime luego un documento.

Espacio de nombres: System.Windows.Controls


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: http://schemas.microsoft.com/winfx/xaml/presentation

Sintaxis

Visual Basic (Declaración)

Public Class PrintDialog

Visual Basic (Uso)


Dim instance As PrintDialog

C#
public class PrintDialog

Visual C++
public ref class PrintDialog

J#
public class PrintDialog

JScript

public class PrintDialog

Uso de elementos de objeto XAML


<PrintDialog .../>

Comentarios

Un usuario puede utilizar el cuadro de diálogo Imprimir para seleccionar una impresora, configurarla y realizar un trabajo de
impresión.

En sentido estricto, puede utilizar el método PrintDocument sin abrir nunca el cuadro de diálogo. En ese sentido, se puede utilizar el
control como un componente de impresión oculto. No obstante, por razones de rendimiento, sería mejor utilizar el método AddJob o
uno de los numerosos métodos Write y WriteAsync de XpsDocumentWriter. Para obtener más información sobre esto, vea Cómo:
Imprimir mediante programación archivos XPS y Printing an XPS Document.

No confunda esta clase, System.Windows.Controls.PrintDialog, con System.Windows.Forms.PrintDialog. Esta última se utiliza con
aplicaciones de formularios Windows Forms. System.Windows.Controls.PrintDialog se utiliza con aplicaciones de Windows
Presentation Foundation (WPF).

Ejemplos

El ejemplo siguiente muestra cómo crear una instancia y mostrar un sencillo PrintDialog mediante marcado y código de Lenguaje de
marcado de aplicaciones extensible (XAML).

XAML Copiar código

<Button Width="200" Click="InvokePrint">Invoke PrintDialog</Button>

...

C# Copiar código

public void InvokePrint(object sender, RoutedEventArgs e)


{
// Create the print dialog object and set options
PrintDialog pDialog = new PrintDialog();
pDialog.PageRangeSelection = PageRangeSelection.AllPages;
pDialog.UserPageRangeEnabled = true;

// Display the dialog. This returns true if the user presses the Print button.
Nullable<Boolean> print = pDialog.ShowDialog();
if (print == true)
{
XpsDocument xpsDocument = new XpsDocument("C:\\FixedDocumentSequence.xps", FileAccess.ReadWrite);
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
pDialog.PrintDocument(fixedDocSeq.DocumentPaginator, "Test print job");
}
}

Jerarquía de herencia
System.Object
System.Windows.Controls.PrintDialog

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la ejecución de subprocesos. No se garantiza
que los miembros de instancias sean seguros para la ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para obtener una lista de las
versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Conceptos
Información general sobre impresión

Referencia
PrintDialog (Miembros)
System.Windows.Controls (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
SaveFileDialog (Clase)
Miembros Vea también Enviar comentarios

Representa un cuadro de diálogo común que permite al usuario especificar un nombre de archivo para
guardar un archivo con ese nombre. Una aplicación que se ejecute con confianza parcial no podrá utilizar
SaveFileDialog.

Espacio de nombres: Microsoft.Win32


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: No asignado a un xmlns.

Sintaxis

Visual Basic (Declaración)


Public NotInheritable Class SaveFileDialog _
Inherits FileDialog

Visual Basic (Uso)


Dim instance As SaveFileDialog

C#
public sealed class SaveFileDialog : FileDialog

Visual C++
public ref class SaveFileDialog sealed : public FileDialog

J#
public final class SaveFileDialog extends FileDialog

JScript
public final class SaveFileDialog extends FileDialog

Uso de elementos de objeto XAML


<SaveFileDialog .../>

Jerarquía de herencia
System.Object
Microsoft.Win32.CommonDialog
Microsoft.Win32.FileDialog
Microsoft.Win32.SaveFileDialog

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la
ejecución de subprocesos. No se garantiza que los miembros de instancias sean seguros para la
ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para
obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Referencia
SaveFileDialog (Miembros)
Microsoft.Win32 (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
InkCanvas (Clase)
Miembros Ejemplo Vea también Enviar comentarios

Define una área que recibe y muestra trazos de entrada manuscrita.

Espacio de nombres: System.Windows.Controls


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: http://schemas.microsoft.com/winfx/xaml/presentation

Sintaxis

Visual Basic (Declaración)


<ContentPropertyAttribute("Children")> _
Public Class InkCanvas _
Inherits FrameworkElement _
Implements IAddChild

Visual Basic (Uso)


Dim instance As InkCanvas

C#
[ContentPropertyAttribute("Children")]
public class InkCanvas : FrameworkElement, IAddChild

Visual C++
[ContentPropertyAttribute(L"Children")]
public ref class InkCanvas : public FrameworkElement,
IAddChild

J#
/** @attribute ContentPropertyAttribute("Children") */
public class InkCanvas extends FrameworkElement implements IAddChild

JScript
public class InkCanvas extends FrameworkElement implements IAddChild

Uso de elementos de objeto XAML


<InkCanvas>
Children
</InkCanvas>

Comentarios

InkCanvas es un elemento que se puede utilizar para recibir y mostrar entradas de entrada
manuscrita. Normalmente esta operación se lleva a cabo mediante el uso de un lápiz o un mouse que
interactúan con un digitalizador para generar trazos de entrada manuscrita. Los trazos creados se
representan como objetos Stroke y se pueden manipular mediante programación o a través de los
datos proporcionados por el usuario. InkCanvas permite al usuario modificar o eliminar un objeto
Stroke existente.

InkCanvas se puede enlazar a un origen de datos. Por ejemplo, puede enlazar la propiedad Strokes a
una cadena codificada en base 64 que contenga los datos de entrada manuscrita en el Formato
serializado de tinta (ISF) o incluso puede enlazarla a la propiedad Strokes de otra clase InkCanvas.
También puede enlazar propiedades, como DefaultDrawingAttributes y EditingMode, a otros orígenes
de datos.
Ejemplos

En el ejemplo siguiente se muestra cómo se simula el uso de un lápiz y un marcador de resaltado en


la misma clase InkCanvas. En este ejemplo se supone que el elemento raíz del archivo de lenguaje
de marcado (XAML) es una clase DockPanel denominada root. También se supone que hay un control
Button denominado switchHighlighter y que los eventos Click y Loaded están conectados al
controlador de eventos del ejemplo.

C# Copiar código

InkCanvas inkCanvas1 = new InkCanvas();


DrawingAttributes inkDA;
DrawingAttributes highlighterDA;
bool useHighlighter = false;

// Add an InkCanvas to the window, and allow the user to


// switch between using a green pen and a purple highlighter
// on the InkCanvas.
private void WindowLoaded(object sender, EventArgs e)
{
inkCanvas1.Background = Brushes.DarkSlateBlue;
inkCanvas1.DefaultDrawingAttributes.Color = Colors.SpringGreen;

root.Children.Add(inkCanvas1);

// Set up the DrawingAttributes for the pen.


inkDA = new DrawingAttributes();
inkDA.Color = Colors.SpringGreen;
inkDA.Height = 5;
inkDA.Width = 5;
inkDA.FitToCurve = false;

// Set up the DrawingAttributes for the highlighter.


highlighterDA = new DrawingAttributes();
highlighterDA.Color = Colors.Orchid;
highlighterDA.IsHighlighter = true;
highlighterDA.IgnorePressure = true;
highlighterDA.StylusTip = StylusTip.Rectangle;
highlighterDA.Height = 30;
highlighterDA.Width = 10;

inkCanvas1.DefaultDrawingAttributes = inkDA;
}

// Create a button called switchHighlighter and use


// SwitchHighlighter_Click to handle the Click event.
// The useHighlighter variable is a boolean that indicates
// whether the InkCanvas renders ink as a highlighter.

// Switch between using the 'pen' DrawingAttributes and the


// 'highlighter' DrawingAttributes.
void SwitchHighlighter_Click(Object sender, RoutedEventArgs e)
{
useHighlighter = !useHighlighter;

if (useHighlighter)
{
switchHighlighter.Content = "Use Pen";
inkCanvas1.DefaultDrawingAttributes = highlighterDA;
}
else
{
switchHighlighter.Content = "Use Highlighter";
inkCanvas1.DefaultDrawingAttributes = inkDA;

}
}

Visual Basic Copiar código

Private WithEvents inkCanvas1 As New InkCanvas()


Private inkDA As DrawingAttributes
Private highlighterDA As DrawingAttributes
Private useHighlighter As Boolean = False

' Add an InkCanvas to the window, and allow the user to


' switch between using a green pen and a purple highlighter
' on the InkCanvas.
Private Sub WindowLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)

inkCanvas1.Background = Brushes.DarkSlateBlue
inkCanvas1.DefaultDrawingAttributes.Color = Colors.SpringGreen

' Add the InkCanvas to the DockPanel, named root.


root.Children.Add(inkCanvas1)

' Set up the DrawingAttributes for the pen.


inkDA = New DrawingAttributes()
With inkDA
.Color = Colors.SpringGreen
.Height = 5
.Width = 5
.FitToCurve = True
End With

' Set up the DrawingAttributes for the highlighter.


highlighterDA = New DrawingAttributes()
With highlighterDA
.Color = Colors.Orchid
.IsHighlighter = True
.IgnorePressure = True
.StylusTip = StylusTip.Rectangle
.Height = 30
.Width = 10
End With

inkCanvas1.DefaultDrawingAttributes = inkDA

End Sub 'WindowLoaded

' Create a button called switchHighlighter and use


' SwitchHighlighter_Click to handle the Click event.
' The useHighlighter variable is a boolean that indicates
' whether the InkCanvas renders ink as a highlighter.

' Switch between using the 'pen' DrawingAttributes and the


' 'highlighter' DrawingAttributes when the user clicks on .
Sub SwitchHighlighter_Click(ByVal sender As [Object], ByVal e As RoutedEventArgs)

useHighlighter = Not useHighlighter

If useHighlighter Then
switchHighlighter.Content = "Use Pen"
inkCanvas1.DefaultDrawingAttributes = highlighterDA
Else

switchHighlighter.Content = "Use Highlighter"


inkCanvas1.DefaultDrawingAttributes = inkDA
End If

End Sub 'SwitchHighlighter_Click


En el ejemplo siguiente se declaran dos objetos InkCanvas en XAML y se establece el enlace de datos
entre ellos y otros orígenes de datos. El primer control InkCanvas, denominado ic , se enlaza a dos
orígenes de datos. Las propiedades EditingMode y DefaultDrawingAttributes de ic se enlazan a
objetos ListBox, que a su vez se enlazan a las matrices definidas en XAML. Las propiedades
EditingMode, DefaultDrawingAttributes y Strokes del segundo objeto InkCanvas están enlazadas al
primer objeto InkCanvas en el código siguiente.

XAML Copiar código

<Canvas>
<Canvas.Resources>
<!--Define an array containing the InkEditingMode Values.-->
<x:Array x:Key="MyEditingModes" x:Type="{x:Type InkCanvasEditingMode}">
<x:Static Member="InkCanvasEditingMode.Ink"/>
<x:Static Member="InkCanvasEditingMode.Select"/>
<x:Static Member="InkCanvasEditingMode.EraseByPoint"/>
<x:Static Member="InkCanvasEditingMode.EraseByStroke"/>
</x:Array>

<!--Define an array containing some DrawingAttributes.-->


<x:Array x:Key="MyDrawingAttributes"
x:Type="{x:Type DrawingAttributes}">
<DrawingAttributes Color="Black" FitToCurve="true"
Width="3" Height="3"/>
<DrawingAttributes Color="Blue" FitToCurve="false"
Width="5" Height="5"/>
<DrawingAttributes Color="Red" FitToCurve="true"
Width="7" Height="7"/>
</x:Array>

<!--Create a DataTemplate to display the


DrawingAttributes shown above-->
<DataTemplate DataType="{x:Type DrawingAttributes}" >
<Border Width="80" Height="{Binding Path=Height}">
<Border.Background >
<SolidColorBrush Color="{Binding Path=Color}"/>
</Border.Background>
</Border>
</DataTemplate>
</Canvas.Resources>

<!--Bind the first InkCavas' DefaultDrawingAtributes to a


Listbox, called lbDrawingAttributes, and its EditingMode to
a ListBox called lbEditingMode.-->
<InkCanvas Name="ic" Background="LightGray"
Canvas.Top="0" Canvas.Left="0"
Height="400" Width="200"
DefaultDrawingAttributes="{Binding
ElementName=lbDrawingAttributes, Path=SelectedItem}"
EditingMode=
"{Binding ElementName=lbEditingMode, Path=SelectedItem}"
>
</InkCanvas>

<!--Bind the Strokes, DefaultDrawingAtributes, and, EditingMode properties of


the second InkCavas the first InkCanvas.-->
<InkCanvas Background="LightBlue"
Canvas.Top="0" Canvas.Left="200"
Height="400" Width="200"
Strokes="{Binding ElementName=ic, Path=Strokes}"
DefaultDrawingAttributes="{Binding
ElementName=ic, Path=DefaultDrawingAttributes}"
EditingMode="{Binding ElementName=ic, Path=EditingMode}">

<InkCanvas.LayoutTransform>
<ScaleTransform ScaleX="-1" ScaleY="1" />
</InkCanvas.LayoutTransform>

</InkCanvas>

<!--Use the array, MyEditingModes, to populate a ListBox-->


<ListBox Name="lbEditingMode"
Canvas.Top="0" Canvas.Left="450"
Height="100" Width="100"
ItemsSource="{StaticResource MyEditingModes}" />

<!--Use the array, MyDrawingAttributes, to populate a ListBox-->


<ListBox Name="lbDrawingAttributes"
Canvas.Top="150" Canvas.Left="450"
Height="100" Width="100"
ItemsSource="{StaticResource MyDrawingAttributes}" />

</Canvas>

Jerarquía de herencia
System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.InkCanvas

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la
ejecución de subprocesos. No se garantiza que los miembros de instancias sean seguros para la
ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para
obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Conceptos
Ejemplo WPF Controls Gallery
Enlace de datos

Referencia
InkCanvas (Miembros)
System.Windows.Controls (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
InkPresenter (Clase)
Miembros Ejemplo Vea también Enviar comentarios

Representa la entrada manuscrita en una superficie.

Espacio de nombres: System.Windows.Controls


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: http://schemas.microsoft.com/winfx/xaml/presentation

Sintaxis

Visual Basic (Declaración)


Public Class InkPresenter _
Inherits Decorator

Visual Basic (Uso)


Dim instance As InkPresenter

C#
public class InkPresenter : Decorator

Visual C++
public ref class InkPresenter : public Decorator

J#
public class InkPresenter extends Decorator

JScript
public class InkPresenter extends Decorator

Uso de elementos de objeto XAML


<InkPresenter>
Child
</InkPresenter>

Comentarios

La representación de entrada manuscrita se produce de dos modos: dinámico y estático. La


representación dinámica se produce según se escribe la entrada manuscrita en una superficie de
escritura a mano: el trazo se representa según se va realizando. La representación estática se produce
una vez recopilados los datos del trazo y asociados a un nuevo trazo.

Para representar la entrada manuscrita dinámicamente mediante InkPresenter, asocie la propiedad


RootVisual de DynamicRenderer a InkPresenter utilizando el método AttachVisuals. Para representar
la entrada manuscrita estáticamente, agregue los objetos del trazo a la propiedad Strokes.

Ejemplos

El ejemplo siguiente crea mediante programación un trazo y lo agrega a InkPresenter. En este


ejemplo sólo aparece una representación estática, en la que se supone que el evento Loaded está
conectado al controlador de eventos, WindowLoaded.

C# Copiar código

public partial class Window1 : Window


{
InkPresenter inkPresenter1;

public Window1()
{
InitializeComponent();

private void WindowLoaded(object sender, RoutedEventArgs e)


{
inkPresenter1 = new InkPresenter();

this.Content = inkPresenter1;

StylusPoint segment1Start = new StylusPoint(200, 110);


StylusPoint segment1End = new StylusPoint(185, 150);
StylusPoint segment2Start = new StylusPoint(185, 150);
StylusPoint segment2End = new StylusPoint(135, 150);
StylusPoint segment3Start = new StylusPoint(135, 150);
StylusPoint segment3End = new StylusPoint(175, 180);
StylusPoint segment4Start = new StylusPoint(175, 180);
StylusPoint segment4End = new StylusPoint(160, 220);
StylusPoint segment5Start = new StylusPoint(160, 220);
StylusPoint segment5End = new StylusPoint(200, 195);
StylusPoint segment6Start = new StylusPoint(200, 195);
StylusPoint segment6End = new StylusPoint(240, 220);
StylusPoint segment7Start = new StylusPoint(240, 220);
StylusPoint segment7End = new StylusPoint(225, 180);
StylusPoint segment8Start = new StylusPoint(225, 180);
StylusPoint segment8End = new StylusPoint(265, 150);
StylusPoint segment9Start = new StylusPoint(265, 150);
StylusPoint segment9End = new StylusPoint(215, 150);
StylusPoint segment10Start = new StylusPoint(215, 150);
StylusPoint segment10End = new StylusPoint(200, 110);

StylusPointCollection strokePoints = new StylusPointCollection();

strokePoints.Add(segment1Start);
strokePoints.Add(segment1End);
strokePoints.Add(segment2Start);
strokePoints.Add(segment2End);
strokePoints.Add(segment3Start);
strokePoints.Add(segment3End);
strokePoints.Add(segment4Start);
strokePoints.Add(segment4End);
strokePoints.Add(segment5Start);
strokePoints.Add(segment5End);
strokePoints.Add(segment6Start);
strokePoints.Add(segment6End);
strokePoints.Add(segment7Start);
strokePoints.Add(segment7End);
strokePoints.Add(segment8Start);
strokePoints.Add(segment8End);
strokePoints.Add(segment9Start);
strokePoints.Add(segment9End);
strokePoints.Add(segment10Start);
strokePoints.Add(segment10End);

Stroke newStroke = new Stroke(strokePoints);


inkPresenter1.Strokes.Add(newStroke);
}
}

Visual Basic Copiar código

Class Window1
Inherits Window '
Private inkPresenter1 As InkPresenter

Public Sub New()


InitializeComponent()

End Sub 'New

Private Sub WindowLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)

inkPresenter1 = New InkPresenter()


Me.Content = inkPresenter1

Dim segment1Start As New StylusPoint(200, 110)


Dim segment1End As New StylusPoint(185, 150)
Dim segment2Start As New StylusPoint(185, 150)
Dim segment2End As New StylusPoint(135, 150)
Dim segment3Start As New StylusPoint(135, 150)
Dim segment3End As New StylusPoint(175, 180)
Dim segment4Start As New StylusPoint(175, 180)
Dim segment4End As New StylusPoint(160, 220)
Dim segment5Start As New StylusPoint(160, 220)
Dim segment5End As New StylusPoint(200, 195)
Dim segment6Start As New StylusPoint(200, 195)
Dim segment6End As New StylusPoint(240, 220)
Dim segment7Start As New StylusPoint(240, 220)
Dim segment7End As New StylusPoint(225, 180)
Dim segment8Start As New StylusPoint(225, 180)
Dim segment8End As New StylusPoint(265, 150)
Dim segment9Start As New StylusPoint(265, 150)
Dim segment9End As New StylusPoint(215, 150)
Dim segment10Start As New StylusPoint(215, 150)
Dim segment10End As New StylusPoint(200, 110)

Dim strokePoints As New StylusPointCollection()

strokePoints.Add(segment1Start)
strokePoints.Add(segment1End)
strokePoints.Add(segment2Start)
strokePoints.Add(segment2End)
strokePoints.Add(segment3Start)
strokePoints.Add(segment3End)
strokePoints.Add(segment4Start)
strokePoints.Add(segment4End)
strokePoints.Add(segment5Start)
strokePoints.Add(segment5End)
strokePoints.Add(segment6Start)
strokePoints.Add(segment6End)
strokePoints.Add(segment7Start)
strokePoints.Add(segment7End)
strokePoints.Add(segment8Start)
strokePoints.Add(segment8End)
strokePoints.Add(segment9Start)
strokePoints.Add(segment9End)
strokePoints.Add(segment10Start)
strokePoints.Add(segment10End)

Dim newStroke As New Stroke(strokePoints)


inkPresenter1.Strokes.Add(newStroke)

End Sub 'WindowLoaded


End Class 'Window1

Jerarquía de herencia
System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Decorator
System.Windows.Controls.InkPresenter

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la
ejecución de subprocesos. No se garantiza que los miembros de instancias sean seguros para la
ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para
obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Referencia
InkPresenter (Miembros)
System.Windows.Controls (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
DocumentViewer (Clase)
Miembros Vea también Enviar comentarios

Representa un control de visualización de documentos que puede hospedar contenido FixedDocument paginado como
XpsDocument.

Espacio de nombres: System.Windows.Controls


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: http://schemas.microsoft.com/winfx/xaml/presentation

Sintaxis

Visual Basic (Declaración)


<TemplatePartAttribute(Name := "PART_FindToolBarHost", Type := GetType(ContentControl))> _
<TemplatePartAttribute(Name := "PART_ContentHost", Type := GetType(ScrollViewer))> _
Public Class DocumentViewer _
Inherits DocumentViewerBase

Visual Basic (Uso)


Dim instance As DocumentViewer

C#
[TemplatePartAttribute(Name = "PART_FindToolBarHost", Type = typeof(ContentControl))]
[TemplatePartAttribute(Name = "PART_ContentHost", Type = typeof(ScrollViewer))]
public class DocumentViewer : DocumentViewerBase

Visual C++
[TemplatePartAttribute(Name = L"PART_FindToolBarHost", Type = typeof(ContentControl))]
[TemplatePartAttribute(Name = L"PART_ContentHost", Type = typeof(ScrollViewer))]
public ref class DocumentViewer : public DocumentViewerBase

J#
/** @attribute TemplatePartAttribute(Name = "PART_FindToolBarHost", Type = ContentControl) */
/** @attribute TemplatePartAttribute(Name = "PART_ContentHost", Type = ScrollViewer) */
public class DocumentViewer extends DocumentViewerBase

JScript
public class DocumentViewer extends DocumentViewerBase

Uso de elementos de objeto XAML


<DocumentViewer>
Document
</DocumentViewer>

Jerarquía de herencia
System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.Primitives.DocumentViewerBase
System.Windows.Controls.DocumentViewer

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la ejecución de
subprocesos. No se garantiza que los miembros de instancias sean seguros para la ejecución de subprocesos.

Plataformas

Windows Vista
.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para obtener una
lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Conceptos
Ejemplo WPF Controls Gallery

Referencia
DocumentViewer (Miembros)
System.Windows.Controls (Espacio de nombres)
DocumentPaginator

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
FlowDocumentPageViewer (Clase)
Miembros Ejemplo Vea también Enviar comentarios

Representa un control para ver el contenido de flujo en un modo de vista fijo que muestra una página de contenido a la vez.

Espacio de nombres: System.Windows.Controls


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: http://schemas.microsoft.com/winfx/xaml/presentation

Sintaxis

Visual Basic (Declaración)


<TemplatePartAttribute(Name := "PART_FindToolBarHost", Type := GetType(Decorator))> _
Public Class FlowDocumentPageViewer _
Inherits DocumentViewerBase

Visual Basic (Uso)


Dim instance As FlowDocumentPageViewer

C#
[TemplatePartAttribute(Name = "PART_FindToolBarHost", Type = typeof(Decorator))]
public class FlowDocumentPageViewer : DocumentViewerBase

Visual C++
[TemplatePartAttribute(Name = L"PART_FindToolBarHost", Type = typeof(Decorator))]
public ref class FlowDocumentPageViewer : public DocumentViewerBase

J#
/** @attribute TemplatePartAttribute(Name = "PART_FindToolBarHost", Type = Decorator) */
public class FlowDocumentPageViewer extends DocumentViewerBase

JScript
public class FlowDocumentPageViewer extends DocumentViewerBase

Uso de elementos de objeto XAML


<FlowDocumentPageViewer>
Document
</FlowDocumentPageViewer>

Comentarios

Modelo de contenido: FlowDocumentPageViewer sólo permite un objeto FlowDocument como elemento


secundario.

FlowDocumentPageViewer muestra el contenido en el modo de vista de una página a la vez. Un control similar,
FlowDocumentScrollViewer, muestra el contenido en modo de desplazamiento continuo. Tanto
FlowDocumentPageViewer como FlowDocumentScrollViewer son fijos para un modo de vista concreto. Por otro
lado, FlowDocumentReader incluye características que permiten al usuario elegir dinámicamente entre varios modos
de vista (suministrados por la enumeración FlowDocumentReaderViewingMode), a costa de que el rendimiento sea
más pobre que el de FlowDocumentPageViewer o FlowDocumentScrollViewer.

En la ilustración siguiente se muestra un control FlowDocumentPageViewer con su interfaz de usuario (UI)


predeterminada.
 Área de contenido: el área de contenido muestra el contenido del objeto FlowDocument especificado por la
propiedad Document.
 Barra de herramientas: la barra de herramientas predeterminada se acopla bajo el área de contenido y hospeda
controles para navegar por las páginas y cambiar el nivel de zoom.
 Controles de navegación de páginas: los controles de navegación de páginas incluyen un botón que permite
saltar a la página siguiente (flecha abajo) o a la página anterior (flecha arriba), así como los indicadores del
número de página actual y el número total de páginas.
 Controles de zoom: los controles de zoom permiten al usuario aumentar o reducir el nivel de zoom haciendo
clic en los botones con el signo más y el signo menos, respectivamente. Los controles de zoom incluyen
también un control deslizante para ajustar el nivel de zoom. Para obtener más información, vea Zoom.
 Búsqueda: el usuario puede utilizar el método abreviado de teclado Ctrl+F o el método Find para alternar un
cuadro de texto de búsqueda que permita buscar cadenas en el contenido. Para obtener más información, vea
Find.

Ejemplos

En el ejemplo siguiente se define el objeto FlowDocumentPageViewer representado en la figura anterior.

XAML Copiar código

<FlowDocumentPageViewer Margin="10" BorderBrush="Black" BorderThickness="1">


<FlowDocument
ColumnWidth="400"
IsOptimalParagraphEnabled="True" IsHyphenationEnabled="True"
>
<Section FontSize="12">
<Paragraph>
<Bold>Neptune</Bold> (planet), major planet in the solar system, eighth planet
from the Sun and fourth largest in diameter. Neptune maintains an almost constant
distance, about 4,490 million km (about 2,790 million mi), from the Sun. Neptune
revolves outside the orbit of Uranus and for most of its orbit moves inside the
elliptical path of the outermost planet Pluto (see Solar System). Every 248 years,
Pluto’s elliptical orbit brings the planet inside Neptune’s nearly circular orbit
for about 20 years, temporarily making Neptune the farthest planet from the Sun.
The last time Pluto’s orbit brought it inside Neptune’s orbit was in 1979. In
1999 Pluto’s orbit carried it back outside Neptune’s orbit.
<Figure
Width="140" Height="50" Background="GhostWhite"
HorizontalAnchor="PageLeft"
HorizontalOffset="100" VerticalOffset="20"
>
<Paragraph
FontStyle="Italic" TextAlignment="Left"
Background="Beige" Foreground="DarkGreen"
>
Neptune has 72 times Earth's volume...
</Paragraph>
</Figure>

<Floater
Background="GhostWhite"
Width="285" HorizontalAlignment="Left"
>
<Table CellSpacing="5">
<Table.Columns>
<TableColumn Width="155"/>
<TableColumn Width="130"/>
</Table.Columns>

<TableRowGroup>
<TableRow>
<TableCell ColumnSpan="3">
<Paragraph>Neptune Stats</Paragraph>
</TableCell>
</TableRow>

<TableRow Background="LightGoldenrodYellow" FontSize="12">


<TableCell>
<Paragraph FontWeight="Bold">Mean Distance from Sun</Paragraph>
</TableCell>
<TableCell>
<Paragraph>4,504,000,000 km</Paragraph>
</TableCell>
</TableRow>

<TableRow FontSize="12" Background="LightGray">


<TableCell>
<Paragraph FontWeight="Bold">Mean Diameter</Paragraph>
</TableCell>
<TableCell>
<Paragraph>49,532 km</Paragraph>
</TableCell>
</TableRow>

<TableRow Background="LightGoldenrodYellow" FontSize="12">


<TableCell>
<Paragraph FontWeight="Bold">Approximate Mass</Paragraph>
</TableCell>
<TableCell>
<Paragraph>1.0247e26 kg</Paragraph>
</TableCell>
</TableRow>
<TableRow>
<TableCell ColumnSpan="4">
<Paragraph FontSize="10" FontStyle="Italic">
Information from the
<Hyperlink
NavigateUri="http://encarta.msn.com/encnet/refpages/artcenter.aspx"
>Encarta</Hyperlink>
web site.
</Paragraph>
</TableCell>
</TableRow>
</TableRowGroup>
</Table>
</Floater>
</Paragraph>
<Paragraph>
Astronomers believe Neptune has an inner rocky core that is surrounded by a vast
ocean of water mixed with rocky material. From the inner core, this ocean extends
upward until it meets a gaseous atmosphere of hydrogen, helium, and trace amounts
of methane. Neptune has four rings and 11 known moons. Even though Neptune's volume
is 72 times Earth’s volume, its mass is only 17.15 times Earth’s mass. Because of
its size, scientists classify Neptune—along with Jupiter, Saturn, and Uranus—as
one of the giant or Jovian planets (so-called because they resemble Jupiter).
</Paragraph>
<Paragraph>
<Figure
Width="140" Height="50"
Background="GhostWhite" TextAlignment="Left"
HorizontalAnchor="PageCenter" WrapDirection="Both"
>
<Paragraph FontStyle="Italic" Background="Beige" Foreground="DarkGreen" >
Neptune has an orbital period of ~20 years...
</Paragraph>
</Figure>
Mathematical theories of astronomy led to the discovery of Neptune. To account for
wobbles in the orbit of the planet Uranus, British astronomer John Couch Adams and
French astronomer Urbain Jean Joseph Leverrier independently calculated the existence
and position of a new planet in 1845 and 1846, respectively. They theorized that the
gravitational attraction of this planet for Uranus was causing the wobbles in Uranus’s
orbit. Using information from Leverrier, German astronomer Johann Gottfried Galle first
observed the planet in 1846.
</Paragraph>
</Section>
</FlowDocument>
</FlowDocumentPageViewer>

Jerarquía de herencia
System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.Primitives.DocumentViewerBase
System.Windows.Controls.FlowDocumentPageViewer

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la ejecución de
subprocesos. No se garantiza que los miembros de instancias sean seguros para la ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para obtener una
lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Conceptos
Información general sobre documentos dinámicos

Referencia
FlowDocumentPageViewer (Miembros)
System.Windows.Controls (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
FlowDocumentReader (Clase)
Miembros Ejemplo Vea también Enviar comentarios

Proporciona un control para ver el contenido dinámico, con compatibilidad integrada para varios modos de vista.

Espacio de nombres: System.Windows.Controls


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: http://schemas.microsoft.com/winfx/xaml/presentation

Sintaxis

Visual Basic (Declaración)


<ContentPropertyAttribute("Document")> _
<TemplatePartAttribute(Name := "PART_ContentHost", Type := GetType(Decorator))> _
<TemplatePartAttribute(Name := "PART_FindToolBarHost", Type := GetType(Decorator))> _
Public Class FlowDocumentReader _
Inherits Control _
Implements IAddChild

Visual Basic (Uso)


Dim instance As FlowDocumentReader

C#
[ContentPropertyAttribute("Document")]
[TemplatePartAttribute(Name = "PART_ContentHost", Type = typeof(Decorator))]
[TemplatePartAttribute(Name = "PART_FindToolBarHost", Type = typeof(Decorator))]
public class FlowDocumentReader : Control, IAddChild

Visual C++
[ContentPropertyAttribute(L"Document")]
[TemplatePartAttribute(Name = L"PART_ContentHost", Type = typeof(Decorator))]
[TemplatePartAttribute(Name = L"PART_FindToolBarHost", Type = typeof(Decorator))]
public ref class FlowDocumentReader : public Control,
IAddChild

J#
/** @attribute ContentPropertyAttribute("Document") */
/** @attribute TemplatePartAttribute(Name = "PART_ContentHost", Type = Decorator) */
/** @attribute TemplatePartAttribute(Name = "PART_FindToolBarHost", Type = Decorator) */
public class FlowDocumentReader extends Control implements IAddChild

JScript
public class FlowDocumentReader extends Control implements IAddChild

Uso de elementos de objeto XAML


<FlowDocumentReader>
Document
</FlowDocumentReader>

Comentarios

FlowDocumentReader dispone de características que permiten al usuario elegir dinámicamente entre distintos
modos de vista, incluido el modo de vista de página única (una página cada vez), dos páginas a la vez (formato de
lectura de libro) y desplazamiento continuo (sin límite). Si no necesita cambiar dinámicamente entre diferentes modos
de vista, hay visores de contenido dinámico más ligeros que disponen de un modo de vista determinado.
FlowDocumentPageViewer muestra el contenido dinámico en una sola página, mientras que FlowDocumentScrollViewer
muestra el contenido dinámico en modo de desplazamiento continuo. Para obtener más información sobre los modos
de presentación disponibles, vea FlowDocumentReaderViewingMode.

En la ilustración siguiente se muestra un control FlowDocumentReader con su interfaz de usuario (UI)


predeterminada.
 Área de contenido: en el área de contenido se muestra el contenido del objeto FlowDocument especificado por la
propiedad Document.
 Barra de herramientas: la barra de herramientas predeterminada se acopla debajo del área de contenido. Tiene
controles que permiten buscar contenido, navegar por las páginas, seleccionar un modo de vista y cambiar el nivel
de zoom.
 Botón Buscar: el botón Buscar abre el cuadro de diálogo Buscar, que permite al usuario buscar determinados
términos o frases en el contenido de FlowDocumentReader. El botón Buscar no se muestra si IsFindEnabled
es false. Para obtener más información, vea Find.
 Controles de navegación de páginas: los controles de navegación de páginas incluyen un botón que permite
saltar a la página siguiente (flecha abajo) o a la página anterior (flecha arriba), así como los indicadores del
número de página actual y el número total de páginas.
 Botones de modos de vista: los botones de modos de vista permiten al usuario seleccionar entre los modos
de vista disponibles. Para obtener más información, vea ViewingMode.
 Controles de zoom: los controles de zoom permiten al usuario aumentar o reducir el nivel de zoom haciendo
clic en los botones con el signo más y el signo menos, respectivamente. Los controles de zoom incluyen
también un control deslizante que permite ajustar el nivel de zoom. Para obtener más información, vea Zoom.

La interfaz de usuario de la barra de herramientas predeterminada no incluye el botón Imprimir.

FlowDocument es el único elemento secundario permitido para FlowDocumentReader. Un elemento


FlowDocumentReader no puede hospedar más que un objeto FlowDocument.

Ejemplos

En el ejemplo siguiente se define el objeto FlowDocumentReader que se muestra en la ilustración anterior.

XAML Copiar código


<FlowDocumentReader>
<FlowDocument
ColumnWidth="400"
IsOptimalParagraphEnabled="True" IsHyphenationEnabled="True"
>
<Section FontSize="12">
<Paragraph>
<Bold>Neptune</Bold> (planet), major planet in the solar system, eighth planet
from the Sun and fourth largest in diameter. Neptune maintains an almost constant
distance, about 4,490 million km (about 2,790 million mi), from the Sun. Neptune
revolves outside the orbit of Uranus and for most of its orbit moves inside the
elliptical path of the outermost planet Pluto (see Solar System). Every 248 years,
Pluto’s elliptical orbit brings the planet inside Neptune’s nearly circular orbit
for about 20 years, temporarily making Neptune the farthest planet from the Sun.
The last time Pluto’s orbit brought it inside Neptune’s orbit was in 1979. In
1999 Pluto’s orbit carried it back outside Neptune’s orbit.

<!-- This Figure uses relative measurements for width and height. -->
<Figure
Width="0.25" Height="0.1" Background="GhostWhite"
HorizontalAnchor="PageLeft"
HorizontalOffset="100" VerticalOffset="20"
>
<Paragraph
FontStyle="Italic" TextAlignment="Left"
Background="Beige" Foreground="DarkGreen"
>
Neptune has 72 times Earth's volume...
</Paragraph>
</Figure>

<!-- This Floater uses relative measurements for width. -->


<Floater
Background="GhostWhite"
Width="0.4" HorizontalAlignment="Left"
>
<Table CellSpacing="5">
<Table.Columns>
<TableColumn Width="155"/>
<TableColumn Width="130"/>
</Table.Columns>

<TableRowGroup>
<TableRow>
<TableCell ColumnSpan="3">
<Paragraph>Neptune Stats</Paragraph>
</TableCell>
</TableRow>

<TableRow Background="LightGoldenrodYellow" FontSize="12">


<TableCell>
<Paragraph FontWeight="Bold">Mean Distance from Sun</Paragraph>
</TableCell>
<TableCell>
<Paragraph>4,504,000,000 km</Paragraph>
</TableCell>
</TableRow>

<TableRow FontSize="12" Background="LightGray">


<TableCell>
<Paragraph FontWeight="Bold">Mean Diameter</Paragraph>
</TableCell>
<TableCell>
<Paragraph>49,532 km</Paragraph>
</TableCell>
</TableRow>

<TableRow Background="LightGoldenrodYellow" FontSize="12">


<TableCell>
<Paragraph FontWeight="Bold">Approximate Mass</Paragraph>
</TableCell>
<TableCell>
<Paragraph>1.0247e26 kg</Paragraph>
</TableCell>
</TableRow>
<TableRow>
<TableCell ColumnSpan="4">
<Paragraph FontSize="10" FontStyle="Italic">
Information from the
<Hyperlink
NavigateUri="http://encarta.msn.com/encnet/refpages/artcenter.aspx"
>Encarta</Hyperlink>
web site.
</Paragraph>
</TableCell>
</TableRow>
</TableRowGroup>
</Table>
</Floater>
</Paragraph>
<Paragraph>
Astronomers believe Neptune has an inner rocky core that is surrounded by a vast
ocean of water mixed with rocky material. From the inner core, this ocean extends
upward until it meets a gaseous atmosphere of hydrogen, helium, and trace amounts
of methane. Neptune has four rings and 11 known moons. Even though Neptune's volume
is 72 times Earth’s volume, its mass is only 17.15 times Earth’s mass. Because of
its size, scientists classify Neptune—along with Jupiter, Saturn, and Uranus—as
one of the giant or Jovian planets (so-called because they resemble Jupiter).
</Paragraph>
<Paragraph>
<Figure
Width="140" Height="50"
Background="GhostWhite" TextAlignment="Left"
HorizontalAnchor="PageCenter" WrapDirection="Both"
>
<Paragraph FontStyle="Italic" Background="Beige" Foreground="DarkGreen" >
Neptune has an orbital period of ~20 years...
</Paragraph>
</Figure>
Mathematical theories of astronomy led to the discovery of Neptune. To account for
wobbles in the orbit of the planet Uranus, British astronomer John Couch Adams and
French astronomer Urbain Jean Joseph Leverrier independently calculated the existence
and position of a new planet in 1845 and 1846, respectively. They theorized that the
gravitational attraction of this planet for Uranus was causing the wobbles in Uranus’s
orbit. Using information from Leverrier, German astronomer Johann Gottfried Galle first
observed the planet in 1846.
</Paragraph>
</Section>
</FlowDocument>
</FlowDocumentReader>

Jerarquía de herencia
System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.FlowDocumentReader

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la ejecución de
subprocesos. No se garantiza que los miembros de instancias sean seguros para la ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para obtener una
lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0
Vea también
Conceptos
Información general sobre documentos dinámicos
Ejemplos de FlowDocumentReader

Referencia
FlowDocumentReader (Miembros)
System.Windows.Controls (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
FlowDocumentScrollViewer (Clase)
Miembros Ejemplo Vea también Enviar comentarios

Proporciona un control para ver contenido dinámico en un modo de desplazamiento continuo.

Espacio de nombres: System.Windows.Controls


Ensamblado: PresentationFramework (en PresentationFramework.dll)
XMLNS para XAML: http://schemas.microsoft.com/winfx/xaml/presentation

Sintaxis

Visual Basic (Declaración)


<TemplatePartAttribute(Name := "PART_FindToolBarHost", Type := GetType(Decorator))> _
<ContentPropertyAttribute("Document")> _
<TemplatePartAttribute(Name := "PART_ContentHost", Type := GetType(ScrollViewer))> _
<TemplatePartAttribute(Name := "PART_ToolBarHost", Type := GetType(Decorator))> _
Public Class FlowDocumentScrollViewer _
Inherits Control _
Implements IAddChild, IServiceProvider

Visual Basic (Uso)


Dim instance As FlowDocumentScrollViewer

C#
[TemplatePartAttribute(Name = "PART_FindToolBarHost", Type = typeof(Decorator))]
[ContentPropertyAttribute("Document")]
[TemplatePartAttribute(Name = "PART_ContentHost", Type = typeof(ScrollViewer))]
[TemplatePartAttribute(Name = "PART_ToolBarHost", Type = typeof(Decorator))]
public class FlowDocumentScrollViewer : Control, IAddChild,
IServiceProvider

Visual C++
[TemplatePartAttribute(Name = L"PART_FindToolBarHost", Type = typeof(Decorator))]
[ContentPropertyAttribute(L"Document")]
[TemplatePartAttribute(Name = L"PART_ContentHost", Type = typeof(ScrollViewer))]
[TemplatePartAttribute(Name = L"PART_ToolBarHost", Type = typeof(Decorator))]
public ref class FlowDocumentScrollViewer : public Control,
IAddChild, IServiceProvider

J#
/** @attribute TemplatePartAttribute(Name = "PART_FindToolBarHost", Type = Decorator) */
/** @attribute ContentPropertyAttribute("Document") */
/** @attribute TemplatePartAttribute(Name = "PART_ContentHost", Type = ScrollViewer) */
/** @attribute TemplatePartAttribute(Name = "PART_ToolBarHost", Type = Decorator) */
public class FlowDocumentScrollViewer extends Control implements IAddChild,
IServiceProvider

JScript
public class FlowDocumentScrollViewer extends Control implements IAddChild, IServiceProvider

Uso de elementos de objeto XAML


<FlowDocumentScrollViewer>
Document
</FlowDocumentScrollViewer>

Comentarios

FlowDocumentScrollViewer muestra contenido en el modo de desplazamiento continuo. Un control similar,


FlowDocumentPageViewer, muestra contenido en el modo de vista de una página a la vez. Tanto
FlowDocumentPageViewer como FlowDocumentScrollViewer son fijos para un modo de vista concreto. Por otro
lado, FlowDocumentReader incluye características que permiten al usuario elegir dinámicamente entre varios modos
de vista (suministrados por la enumeración FlowDocumentReaderViewingMode), a costa de ser más pesado que
FlowDocumentPageViewer o FlowDocumentScrollViewer.

En la ilustración siguiente se muestra un control FlowDocumentScrollViewer con su interfaz de usuario (UI)


predeterminada.
De forma predeterminada, se muestra siempre una barra de desplazamiento vertical y una barra de desplazamiento
horizontal se vuelve visible si es necesario. La interfaz de usuario predeterminada para FlowDocumentScrollViewer
no incluye barra de herramientas; sin embargo, se puede utilizar la propiedad IsToolBarVisible para habilitar una barra
de herramientas integrada.

FlowDocument es el único elemento secundario permitido para FlowDocumentScrollViewer. Un elemento


FlowDocumentScrollViewer no puede alojar más de un objeto FlowDocument.

Ejemplos

En el ejemplo siguiente se define el objeto FlowDocumentScrollViewer representado en la figura anterior.

XAML Copiar código

<FlowDocumentScrollViewer Margin="10" BorderBrush="Black" BorderThickness="1">


<FlowDocument
ColumnWidth="400"
IsOptimalParagraphEnabled="True" IsHyphenationEnabled="True"
>
<Section FontSize="12">
<Paragraph>
<Bold>Neptune</Bold> (planet), major planet in the solar system, eighth planet
from the Sun and fourth largest in diameter. Neptune maintains an almost constant
distance, about 4,490 million km (about 2,790 million mi), from the Sun. Neptune
revolves outside the orbit of Uranus and for most of its orbit moves inside the
elliptical path of the outermost planet Pluto (see Solar System). Every 248 years,
Pluto’s elliptical orbit brings the planet inside Neptune’s nearly circular orbit
for about 20 years, temporarily making Neptune the farthest planet from the Sun.
The last time Pluto’s orbit brought it inside Neptune’s orbit was in 1979. In
1999 Pluto’s orbit carried it back outside Neptune’s orbit.
<Figure
Width="140" Height="50" Background="GhostWhite"
HorizontalAnchor="PageLeft"
HorizontalOffset="100" VerticalOffset="20"
>
<Paragraph
FontStyle="Italic" TextAlignment="Left"
Background="Beige" Foreground="DarkGreen"
>
Neptune has 72 times Earth's volume...
</Paragraph>
</Figure>
<Floater
Background="GhostWhite"
Width="285" HorizontalAlignment="Left"
>
<Table CellSpacing="5">
<Table.Columns>
<TableColumn Width="155"/>
<TableColumn Width="130"/>
</Table.Columns>

<TableRowGroup>
<TableRow>
<TableCell ColumnSpan="3">
<Paragraph>Neptune Stats</Paragraph>
</TableCell>
</TableRow>

<TableRow Background="LightGoldenrodYellow" FontSize="12">


<TableCell>
<Paragraph FontWeight="Bold">Mean Distance from Sun</Paragraph>
</TableCell>
<TableCell>
<Paragraph>4,504,000,000 km</Paragraph>
</TableCell>
</TableRow>

<TableRow FontSize="12" Background="LightGray">


<TableCell>
<Paragraph FontWeight="Bold">Mean Diameter</Paragraph>
</TableCell>
<TableCell>
<Paragraph>49,532 km</Paragraph>
</TableCell>
</TableRow>

<TableRow Background="LightGoldenrodYellow" FontSize="12">


<TableCell>
<Paragraph FontWeight="Bold">Approximate Mass</Paragraph>
</TableCell>
<TableCell>
<Paragraph>1.0247e26 kg</Paragraph>
</TableCell>
</TableRow>
<TableRow>
<TableCell ColumnSpan="4">
<Paragraph FontSize="10" FontStyle="Italic">
Information from the
<Hyperlink
NavigateUri="http://encarta.msn.com/encnet/refpages/artcenter.aspx"
>Encarta</Hyperlink>
web site.
</Paragraph>
</TableCell>
</TableRow>
</TableRowGroup>
</Table>
</Floater>
</Paragraph>
<Paragraph>
Astronomers believe Neptune has an inner rocky core that is surrounded by a vast
ocean of water mixed with rocky material. From the inner core, this ocean extends
upward until it meets a gaseous atmosphere of hydrogen, helium, and trace amounts
of methane. Neptune has four rings and 11 known moons. Even though Neptune's volume
is 72 times Earth’s volume, its mass is only 17.15 times Earth’s mass. Because of
its size, scientists classify Neptune—along with Jupiter, Saturn, and Uranus—as
one of the giant or Jovian planets (so-called because they resemble Jupiter).
</Paragraph>
<Paragraph>
<Figure
Width="140" Height="50"
Background="GhostWhite" TextAlignment="Left"
HorizontalAnchor="PageCenter" WrapDirection="Both"
>
<Paragraph FontStyle="Italic" Background="Beige" Foreground="DarkGreen" >
Neptune has an orbital period of ~20 years...
</Paragraph>
</Figure>
Mathematical theories of astronomy led to the discovery of Neptune. To account for
wobbles in the orbit of the planet Uranus, British astronomer John Couch Adams and
French astronomer Urbain Jean Joseph Leverrier independently calculated the existence
and position of a new planet in 1845 and 1846, respectively. They theorized that the
gravitational attraction of this planet for Uranus was causing the wobbles in Uranus’s
orbit. Using information from Leverrier, German astronomer Johann Gottfried Galle first
observed the planet in 1846.
</Paragraph>
</Section>
</FlowDocument>
</FlowDocumentScrollViewer>

Jerarquía de herencia
System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.FlowDocumentScrollViewer

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la ejecución de
subprocesos. No se garantiza que los miembros de instancias sean seguros para la ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para obtener una
lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Conceptos
Información general sobre documentos dinámicos

Referencia
FlowDocumentScrollViewer (Miembros)
System.Windows.Controls (Espacio de nombres)

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Biblioteca de clases de .NET Framework
StickyNoteControl (Clase)
Miembros Ejemplo Vea también Enviar comentarios

Representa un control que permite que los usuarios asocien a los documentos anotaciones escritas a mano o texto
escrito a máquina.

Espacio de nombres: System.Windows.Controls


Ensamblado: PresentationFramework (en PresentationFramework.dll)

Sintaxis

Visual Basic (Declaración)

<TemplatePartAttribute(Name := "PART_EraseMenuItem", Type := GetType(MenuItem))> _


<TemplatePartAttribute(Name := "PART_SelectMenuItem", Type := GetType(MenuItem))> _
<TemplatePartAttribute(Name := "PART_CloseButton", Type := GetType(Button))> _
<TemplatePartAttribute(Name := "PART_TitleThumb", Type := GetType(Thumb))> _
<TemplatePartAttribute(Name := "PART_ResizeBottomRightThumb", Type := GetType(Thumb))> _
<TemplatePartAttribute(Name := "PART_ContentControl", Type := GetType(ContentControl))> _
<TemplatePartAttribute(Name := "PART_IconButton", Type := GetType(Button))> _
<TemplatePartAttribute(Name := "PART_CopyMenuItem", Type := GetType(MenuItem))> _
<TemplatePartAttribute(Name := "PART_PasteMenuItem", Type := GetType(MenuItem))> _
<TemplatePartAttribute(Name := "PART_InkMenuItem", Type := GetType(MenuItem))> _
Public NotInheritable Class StickyNoteControl _
Inherits Control

Visual Basic (Uso)


Dim instance As StickyNoteControl

C#
[TemplatePartAttribute(Name = "PART_EraseMenuItem", Type = typeof(MenuItem))]
[TemplatePartAttribute(Name = "PART_SelectMenuItem", Type = typeof(MenuItem))]
[TemplatePartAttribute(Name = "PART_CloseButton", Type = typeof(Button))]
[TemplatePartAttribute(Name = "PART_TitleThumb", Type = typeof(Thumb))]
[TemplatePartAttribute(Name = "PART_ResizeBottomRightThumb", Type = typeof(Thumb))]
[TemplatePartAttribute(Name = "PART_ContentControl", Type = typeof(ContentControl))]
[TemplatePartAttribute(Name = "PART_IconButton", Type = typeof(Button))]
[TemplatePartAttribute(Name = "PART_CopyMenuItem", Type = typeof(MenuItem))]
[TemplatePartAttribute(Name = "PART_PasteMenuItem", Type = typeof(MenuItem))]
[TemplatePartAttribute(Name = "PART_InkMenuItem", Type = typeof(MenuItem))]
public sealed class StickyNoteControl : Control

Visual C++
[TemplatePartAttribute(Name = L"PART_EraseMenuItem", Type = typeof(MenuItem))]
[TemplatePartAttribute(Name = L"PART_SelectMenuItem", Type = typeof(MenuItem))]
[TemplatePartAttribute(Name = L"PART_CloseButton", Type = typeof(Button))]
[TemplatePartAttribute(Name = L"PART_TitleThumb", Type = typeof(Thumb))]
[TemplatePartAttribute(Name = L"PART_ResizeBottomRightThumb", Type = typeof(Thumb))]
[TemplatePartAttribute(Name = L"PART_ContentControl", Type = typeof(ContentControl))]
[TemplatePartAttribute(Name = L"PART_IconButton", Type = typeof(Button))]
[TemplatePartAttribute(Name = L"PART_CopyMenuItem", Type = typeof(MenuItem))]
[TemplatePartAttribute(Name = L"PART_PasteMenuItem", Type = typeof(MenuItem))]
[TemplatePartAttribute(Name = L"PART_InkMenuItem", Type = typeof(MenuItem))]
public ref class StickyNoteControl sealed : public Control

J#
/** @attribute TemplatePartAttribute(Name = "PART_EraseMenuItem", Type = MenuItem) */
/** @attribute TemplatePartAttribute(Name = "PART_SelectMenuItem", Type = MenuItem) */
/** @attribute TemplatePartAttribute(Name = "PART_CloseButton", Type = Button) */
/** @attribute TemplatePartAttribute(Name = "PART_TitleThumb", Type = Thumb) */
/** @attribute TemplatePartAttribute(Name = "PART_ResizeBottomRightThumb", Type = Thumb) */
/** @attribute TemplatePartAttribute(Name = "PART_ContentControl", Type = ContentControl) */
/** @attribute TemplatePartAttribute(Name = "PART_IconButton", Type = Button) */
/** @attribute TemplatePartAttribute(Name = "PART_CopyMenuItem", Type = MenuItem) */
/** @attribute TemplatePartAttribute(Name = "PART_PasteMenuItem", Type = MenuItem) */
/** @attribute TemplatePartAttribute(Name = "PART_InkMenuItem", Type = MenuItem) */
public final class StickyNoteControl extends Control
JScript
public final class StickyNoteControl extends Control

XAML
No se puede crear una instancia de esta clase directamente en XAML.

Comentarios

Una nota rápida proporciona una área rectangular cuyo contenido es independiente del texto, imagen u otro
material donde se encuentre delimitada la nota.

La clase StickyNoteControl y sus miembros son públicos, de modo que se le puede asignar un estilo, pero no se
trata de un constructor público. Las instancias se crean con CreateTextStickyNoteCommand y
CreateInkStickyNoteCommand de la clase AnnotationService.

Cuando se crea una nota rápida, se designa como uno de estos dos tipos:
 Las notas rápidas de texto tienen una área de contenido RichTextBox en la que se puede escribir y que se
puede editar como cualquier otra área de texto enriquecido. Los usuarios pueden escribir en ella, así como
cortar, copiar y pegar tanto dentro de la nota como entre la nota y otras aplicaciones. También pueden pegarse
imágenes en la nota. Los métodos abreviados de teclado de texto enriquecido normales también se encuentran
disponibles.

 Las notas rápidas manuscritas tienen una área de contenido InkCanvas que puede editarse como cualquier
otro lienzo de entrada manuscrita. Por ejemplo, pueden borrarse trazos. Con un Tablet PC u otro hardware
adecuado, los usuarios pueden escribir notas a mano.

La interfaz de usuario (UI) de StickyNoteControl hace que se convierta en una forma más eficaz de anotar
material que añadir marcas a una impresión o utilizar notas físicas escritas a mano. También resulta más flexible
que simplemente agregar o tachar el texto de un documento.
 Es posible cambiar el tamaño de las notas rápidas.
 Las notas rápidas pueden minimizarse en un icono y expandirse.
 Una nota rápida, cuando se maximiza, puede arrastrarse hasta una nueva posición en una ventana sin
necesidad de cambiar la ubicación de su delimitador.
 El contenido exacto al que se aplica una nota rápida se resalta y incluye entre corchetes.

 Es posible aplicar dos o más notas rápidas al mismo contenido o a contenido superpuesto.
 Si se produce algún cambio en el contenido del documento en el que está delimitada nota rápida, la nota rápida
pasa a una posición relativa al contenido al que estaba enlazada.
 En el caso de las notas rápidas de texto, las líneas ajustarán automáticamente. Si se modifica el tamaño de la
nota, las líneas volverán a ajustarse en función de las necesidades. Si el contenido se extiende por debajo de la
parte inferior de la nota, aparecerá una barra de desplazamiento vertical.
 En el caso de las notas rápidas manuscritas, aparecerán barras de desplazamiento verticales y horizontales
siempre que el contenido se extienda más allá de los límites de la nota.

Ejemplos

En el ejemplo siguiente se muestra cómo pueden configurarse los comandos de menú de DocumentViewer para
ejecutar CreateTextStickyNoteCommand y CreateInkStickyNoteCommand de la clase AnnotationService. Encontrará
el ejemplo completo en Ejemplo DocumentViewer with Annotations XPS-Store. En el ejemplo se muestra cómo leer
un documento de XML Paper Specification (XPS) en un control DocumentViewer y, a continuación, cómo habilitar la
compatibilidad necesaria para agregar notas rápidas creadas por usuario.

XAML Copiar código

<DocumentViewer.ContextMenu>
<ContextMenu>
<MenuItem Command="ApplicationCommands.Copy" />
<Separator />
<!-- Add a Highlight annotation to a user selection. -->
<MenuItem Command="ann:AnnotationService.CreateHighlightCommand"
Header="Add Highlight" />
<!-- Add a Text Note annotation to a user selection. -->
<MenuItem Command="ann:AnnotationService.CreateTextStickyNoteCommand"
Header="Add Text Note" />
<!-- Add an Ink Note annotation to a user selection. -->
<MenuItem Command="ann:AnnotationService.CreateInkStickyNoteCommand"
Header="Add Ink Note" />
<Separator />
<!-- Remove Highlights from a user selection. -->
<MenuItem Command="ann:AnnotationService.ClearHighlightsCommand"
Header="Remove Highlights" />
<!-- Remove Text Notes and Ink Notes from a user selection. -->
<MenuItem Command="ann:AnnotationService.DeleteStickyNotesCommand"
Header="Remove Notes" />
<!-- Remove Highlights, Text Notes, Ink Notes from a selection. -->
<MenuItem Command="ann:AnnotationService.DeleteAnnotationsCommand"
Header="Remove Highlights &amp; Notes" />
</ContextMenu>
</DocumentViewer.ContextMenu>

Jerarquía de herencia
System.Object
System.Windows.Threading.DispatcherObject
System.Windows.DependencyObject
System.Windows.Media.Visual
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control
System.Windows.Controls.StickyNoteControl

Seguridad para subprocesos


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la ejecución de
subprocesos. No se garantiza que los miembros de instancias sean seguros para la ejecución de subprocesos.

Plataformas

Windows Vista

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para obtener una
lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Información de versión
.NET Framework
Compatible con: 3.5, 3.0 SP1, 3.0

Vea también
Conceptos
Información general sobre anotaciones

Referencia
StickyNoteControl (Miembros)
System.Windows.Controls (Espacio de nombres)
AnnotationService

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Windows Presentation Foundation
Información general sobre recursos
Vea también Enviar comentarios

En esta introducción se describe el uso de los recursos de WPF como una manera simple de reutilizar los objetos y valores que se definen de
forma común. Esta introducción se centra en cómo utilizar los recursos en XAML. También se pueden crear y obtener acceso a los recursos
utilizando código o, de forma intercambiable, código y Lenguaje de marcado de aplicaciones extensible (XAML). Para obtener más
información, vea Recursos y código.
Este tema contiene las secciones siguientes.
 Utilizar recursos en XAML
 Recursos estáticos y recursos dinámicos
 Estilos, plantillas de datos y claves implícitas
 Temas relacionados

Utilizar recursos en XAML


En el ejemplo siguiente se define un objeto SolidColorBrush como un recurso en el elemento raíz de una página. A continuación, el
ejemplo hace referencia al recurso y lo utiliza para establecer las propiedades de varios elementos secundarios, incluyendo un objeto
Ellipse, un objeto TextBlock y un objeto Button.
XAML
<Page Name="root"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Page.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="Blue"/>
</Style>
<Style TargetType="TextBlock" x:Key="TitleText">
<Setter Property="Background" Value="Blue"/>
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="#4E87D4"/>
<Setter Property="FontFamily" Value="Trebuchet MS"/>
<Setter Property="Margin" Value="0,40,10,10"/>
</Style>
<Style TargetType="TextBlock" x:Key="Label">
<Setter Property="DockPanel.Dock" Value="Right"/>
<Setter Property="FontSize" Value="8"/>
<Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,3,10,0"/>
</Style>
</Page.Resources>
<StackPanel>
<Border Style="{StaticResource PageBackground}">
<DockPanel>
<TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
<TextBlock Style="{StaticResource Label}">Label</TextBlock>
<TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Te
<Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">B
<Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margi
</DockPanel>
</Border>
</StackPanel>
</Page>

Cada elemento del marco de trabajo (FrameworkElement o FrameworkContentElement) tiene una propiedad Resources, que es la que
contiene los recursos (como un objeto ResourceDictionary) definidos por un recurso. Los recursos se pueden definir en cualquier
elemento. Sin embargo, normalmente se definen en el elemento raíz que, en el ejemplo, es Page.
Cada recurso incluido en un diccionario de recursos debe tener una clave única. Al definir los recursos en el marcado, se asigna la clave
única a través de x:Key (atributo). Normalmente, la clave es una cadena; sin embargo, también se puede establecer en objetos de otros
tipos utilizando las extensiones de marcado adecuadas. Las claves de recursos que no son de cadena se utilizan en ciertas áreas de
características en WPF, principalmente en los estilos, los recursos de componentes y los estilos de datos.
Una vez definido un recurso, se puede hacer referencia al recurso que se debe utilizar para un valor de propiedad utilizando una sintaxis
de extensión de marcado de recursos que especifique el nombre de la clave, como por ejemplo:
XAML Copiar código
<Button Background="{StaticResource MyBrush}"/>
<Ellipse Fill="{StaticResource MyBrush}"/>

En el ejemplo anterior, cuando el cargador XAML procesa el valor {StaticResource MyBrush} para la propiedad Background de
Button, la lógica de búsqueda de recursos comprueba primero la existencia del elemento Button en el diccionario de recursos. Si Button
no tiene una definición de la clave de recurso MyBrush (no la tiene; su colección de recursos está vacía), la búsqueda comprueba a
continuación el elemento primario de Button, que es Page. Así, cuando se define un recurso en el elemento raíz Page, todos los
elementos del árbol lógico del objeto Page pueden tener acceso a él y se puede reutilizar el mismo recurso para establecer el valor de
cualquier propiedad que acepte el objeto Type que representa el recurso. En el ejemplo anterior, el mismo recurso MyBrush establece
dos propiedades diferentes: la propiedad Background de un objeto Button y la propiedad Fill de un objeto Rectangle.

Recursos estáticos y recursos dinámicos


Se puede hacer referencia a un recurso como un recurso estático o como un recurso dinámico. Para ello, se utilizan las extensiones de
marcado Extensión de marcado StaticResource o Extensión de marcado DynamicResource. Una extensión de marcado es una
característica de XAML que permite especificar una referencia de objeto y que procesa la cadena del atributo y devuelve el objeto a un
cargador XAML. Para obtener más información sobre el comportamiento de la extensión de marcado, vea Extensiones de marcado y
XAML.
Cuando se utiliza una extensión de marcado, normalmente se proporcionan uno o varios parámetros en forma de cadena que son
procesados por dicha extensión de marcado, en lugar de evaluarse en el contexto de la propiedad que se está estableciendo. Extensión
de marcado StaticResource procesa una clave buscando el valor para dicha clave en todos los diccionarios de recursos disponibles. Esto
sucede durante la carga, que es el momento en el que el proceso de carga necesita asignar el valor de la propiedad que acepta la
referencia de recurso estático. Extensión de marcado DynamicResource, por el contrario, procesa una clave creando una expresión, y
dicha expresión permanece sin evaluar hasta que se ejecuta la aplicación, momento en el cual se evalúa y proporciona un valor.
Al hacer referencia a un recurso, las consideraciones siguientes pueden influir a la hora de decidir si se va a utilizar una referencia de
recurso estático o una referencia de recurso dinámico:
 El diseño general utilizado para crear los recursos para la aplicación (por página, en la aplicación, en XAML separado, en un
ensamblado sólo para recursos).
 La funcionalidad de la aplicación: ¿la actualización de recursos en tiempo real forma parte de los requisitos de la aplicación?
 El comportamiento de búsqueda respectivo de ese tipo de referencia de recurso.
 El tipo concreto de recurso o de propiedad, así como el comportamiento nativo de esos tipos.

Recursos estáticos
Las referencias de recursos estáticos funcionan mejor en las circunstancias siguientes:
 No tiene ninguna intención de cambiar el valor del recurso una vez que ha hecho referencia a él por primera vez.
 El diseño de la aplicación concentra la mayoría de sus recursos en diccionarios de recursos en el nivel de aplicación o de página. Las
referencias de recursos estáticos no se vuelven a evaluar basándose en los comportamientos en tiempo de ejecución, como recargar
una página, por lo que puede haber cierta mejora en el rendimiento si se evita el uso de grandes cantidades de referencias de
recursos dinámicos cuando no son necesarias para el diseño de los recursos y de la aplicación.
 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 aplicación 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 búsqueda de referencia de recursos dinámicos, sino el comportamiento de referencia de
recursos estáticos con objeto de que la búsqueda sea predecible y se circunscriba al tema. Con una referencia de recursos dinámicos,
incluso una referencia dentro de un tema permanecerá sin evaluar hasta el tiempo de ejecución, y existe la posibilidad de que cuando
se aplique el tema, algún 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 búsqueda. Si este es el caso, el tema no se comportará de la manera
esperada.
 Está utilizando los recursos para establecer un gran número 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 expresión que se ha vuelto a evaluar y podrá devolver el último valor efectivo. Esta técnica puede
suponer una mejora en el rendimiento.

Comportamiento de la búsqueda de recursos estáticos


1. El proceso de búsqueda comprueba la presencia de la clave solicitada dentro del diccionario de recursos definido por el elemento que
establece la propiedad.
2. A continuación, el proceso de búsqueda recorre en sentido ascendente el árbol lógico, hacia el elemento primario y su diccionario de
recursos. Este proceso continúa hasta que se alcanza el elemento raíz.
3. Por último, se comprueban los recursos de la aplicación. Los recursos de la aplicación son los existentes dentro del diccionario de
recursos definido por el objeto Application para la aplicación de WPF.
Las referencias de recursos estáticos desde un diccionario de recursos deben hacer referencia a un recurso que haya sido definido
léxicamente con anterioridad. Las referencias adelantadas no se pueden resolver mediante una referencia de recurso estático. Por este
motivo, si utiliza referencias de recursos estáticos, debe diseñar la estructura de los diccionarios de recursos de tal forma que los
recursos pensados para su uso individual se definan en o cerca del principio de los respectivos diccionarios.
La búsqueda de recursos estáticos se puede ampliar a los temas, o a los recursos del sistema, pero esto sólo se admite porque el
cargador XAML aplaza la solicitud. Este aplazamiento es necesario para que el tema en tiempo de ejecución en el momento cargar la
página se aplique correctamente a la aplicación. Sin embargo, no se recomienda el uso de referencias de recursos estáticos a claves que
sólo existen en temas o como recursos del sistema. Esto se debe a que dichas referencias no se vuelven a evaluar si el usuario cambia el
tema en tiempo real. Las referencias de recursos dinámicos son más confiables cuando se solicitan recursos del tema o del sistema. La
excepción se produce cuando el propio elemento del tema solicita otro recurso. Por las razones mencionadas anteriormente, estas
referencias deberían ser referencias de recursos estáticos.
El comportamiento de excepción varía si no se encuentra una referencia de recurso estático. Si se aplazase el recurso, la excepción se
produciría en tiempo de ejecución. Si no se aplazase el recurso, la excepción se produciría en el momento de la carga.

Recursos dinámicos
Los recursos dinámicos funcionan mejor en las circunstancias siguientes:
 El valor del recurso depende de condiciones que no se conocen hasta el tiempo de ejecución. Esto incluye los recursos del sistema, o
los recursos que de otra forma serían 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 auténticamente dinámicos porque proceden del entorno en tiempo de ejecución del usuario y del sistema operativo. También es
posible tener temas de nivel de aplicación que pueden cambiar, en los que el acceso a recursos de nivel de página también debe
capturar los cambios.
 Está creando o haciendo referencia a los estilos del tema para un control personalizado.
 Desea ajustar el contenido de un objeto ResourceDictionary durante la duración de una aplicación.
 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 estáticos, las referencias de recursos dinámicos admiten las referencias
adelantadas, ya que no es necesario evaluar el recurso hasta el tiempo de ejecución y, por consiguiente, las referencias adelantadas
no son un concepto pertinente.
 Está haciendo referencia a un recurso que es de gran tamaño desde la perspectiva de un espacio de compilación o de trabajo, y es
posible que dicho recurso no se utilice inmediatamente al cargar la página. Las referencias de recursos estáticos siempre se cargan
desde XAML al cargar la página; sin embargo, una referencia de un recurso dinámico no lo hace hasta que se utiliza realmente.
 Está creando un estilo cuyos valores de establecedor podrían proceder de otros valores influenciados por los temas o por otras
configuraciones del usuario.
 Está aplicando recursos a elementos que podrían haber cambiado de elemento primario en el árbol lógico durante la duración de la
aplicación. Al cambiar el elemento primario, también se cambia potencialmente el ámbito de búsqueda 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 dinámico.

Comportamiento de la búsqueda de recursos dinámicos


El comportamiento de búsqueda de recursos para una referencia de recurso dinámico es similar al comportamiento de búsqueda
establecido en el código si se llama a FindResource o a SetResourceReference.
1. El proceso de búsqueda comprueba la presencia de la clave solicitada dentro del diccionario de recursos definido por el elemento que
establece la propiedad.
 Si el elemento define una propiedad Style, se comprueba el diccionario Resources dentro de Style.
 Si el elemento define una propiedad Template, se comprueba el diccionario Resources dentro de FrameworkTemplate.
2. A continuación, el proceso de búsqueda recorre en sentido ascendente el árbol lógico, hacia el elemento primario y su diccionario de
recursos. Este proceso continúa hasta que se alcanza el elemento raíz.
3. Por último, se comprueban los recursos de la aplicación. Los recursos de la aplicación son los existentes dentro del diccionario de
recursos definido por el objeto Application para la aplicación de WPF.
4. Se comprueba la existencia del tema activo actualmente en el diccionario de recursos de temas. Si el tema cambia en tiempo de
ejecución, se vuelve a evaluar el valor.
5. Se comprueban los recursos del sistema.
El comportamiento de excepción (si existe) varía:
 Si una llamada a FindResource solicita un recurso, y éste no se encuentra, se inicia una excepción.
 Si una llamada a TryFindResource solicita un recurso, y éste no se encuentra, no se inicia ninguna excepción, pero el valor devuelto
es null. Si la propiedad que se establece no acepta null, todavía es posible que se inicie un excepción más profunda (esto depende
de la propiedad individual que se esté estableciendo).
 Si una referencia de recurso dinámico solicitara un recurso en XAML, y éste no se encontrara, el comportamiento dependerá del
sistema general de propiedades, pero el comportamiento general es como si no se hubiera producido ninguna operación de
configuración de propiedades en el nivel en el que existe el recurso. Por ejemplo, si intenta establecer el fondo de un elemento de
botón individual utilizando un recurso que no se ha podido evaluar, no se devuelve ningún conjunto de valores, pero el valor efectivo
todavía puede proceder de otros participantes en el sistema de propiedades y en la prioridad de valores. Por ejemplo, el valor del
fondo todavía podría proceder de un estilo de botón definido localmente o del estilo del tema. Para las propiedades que no se definen
en los estilos de tema, el valor efectivo después de una evaluación de recursos con errores podría proceder del valor predeterminado
en los metadatos de la propiedad.

Restricciones
Las referencias de recursos dinámicos tienen algunas restricciones importantes. Al menos debe cumplirse una de las condiciones
siguientes:
 La propiedad que se establece debe ser una propiedad en un objeto FrameworkElement o FrameworkContentElement. Dicha
propiedad debe estar respaldada por un objeto DependencyProperty.
 La referencia es para un valor dentro de un objeto Style Setter.
 La propiedad que se establece debe ser una propiedad en un objeto Freezable que se proporciona como un valor para una propiedad
de FrameworkElement o FrameworkContentElement, o un valor Setter.
Dado que la propiedad que se establece debe ser una propiedad de DependencyProperty o Freezable, la mayoría de los cambios en la
propiedad se pueden propagar a la interfaz de usuario debido a que dichos cambios (el valor de recurso dinámico modificado) están
confirmados por el sistema de propiedades. La mayoría de los controles incluyen lógica que forzará otro diseño del control si cambia un
objeto DependencyProperty y esa propiedad podría afectar al diseño. Sin embargo, no está garantizado que todas las propiedades que
tengan una Extensión de marcado DynamicResource como valor proporcionen éste de manera que se actualicen en tiempo real en la
interfaz de usuario. Esa funcionalidad podría variar dependiendo de la propiedad, así como del tipo que posea ésta o incluso de la
estructura lógica de la aplicación.

Estilos, plantillas de datos y claves implícitas


Anteriormente, se ha dicho que todos los elementos de un objeto ResourceDictionary deben tener una clave. Sin embargo, eso no
significa que todos los recursos deben tener un atributo x:Key explícito. Varios tipos de objetos admiten una clave implícita cuando se
definen como un recurso, donde el valor de la clave está asociado al valor de otra propiedad. Esto se conoce como una clave implícita,
mientras que un atributo x:Key es una clave explícita. Se puede sobrescribir cualquier clave implícita especificando una clave explícita.
Un escenario muy importante para los recursos es el obtenido al definir un objeto Style. De hecho, Style se define casi siempre como
una entrada en un diccionario de recursos, ya que los estilos están pensados intrínsecamente para su reutilización. Para obtener más
información acerca de los estilos, vea Aplicar estilos y plantillas.
Los estilos para los controles se pueden crear con una clave implícita; así mismo, también se puede hacer referencia a ellos mediante
dicha clave. Los estilos del tema que definen la apariencia predeterminada de un control se basan en esta clave implícita. La clave
implícita desde el punto de vista de la solicitud es el objeto Type del propio control. La clave implícita desde el punto de vista de la
definición del recurso es la propiedad TargetType del estilo. Por consiguiente, si está creando temas para controles personalizados, al
crear estilos que interactúan con estilos de tema existentes no necesita especificar un x:Key (atributo) para ese objeto Style. Y si desea
utilizar los estilos con tema, no es necesario que especifique ningún estilo. Por ejemplo, la definición de estilo siguiente funciona, aunque
el recurso Style no parece tener una clave:
XAML Copiar código
<Style TargetType="Button">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="AliceBlue"/>
<GradientStop Offset="1.0" Color="Salmon"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="18"/>
</Style>

En realidad, el estilo tiene una clave: la clave implícita typeof(Button). En el marcado, puede especificar directamente una propiedad
TargetType como nombre del tipo (o también puede utilizar {x:Type...} para devolver un objeto Type.
A través de los mecanismos de estilo del tema predeterminado utilizados por WPF, ese estilo se aplica como el estilo en tiempo de
ejecución de un objeto Button en la página, aunque el propio objeto Button no intenta especificar su propiedad Style o una referencia de
recurso concreta al estilo. El estilo definido en la página se encontrará antes que el estilo de diccionario de tema en la secuencia de
búsqueda, utilizando la misma clave que este último estilo. También podría especificar <Button>Hello</Button> en cualquier lugar de
la página, y el estilo definido con la propiedad TargetType de Button se aplicaría a ese botón. Si lo desea, también puede asignar
explícitamente al estilo el mismo valor de tipo que TargetType, por motivos de claridad en el marcado, pero eso es opcional.
Las claves implícitas para los estilos no se aplican en un control si OverridesDefaultStyle es true (observe también que
OverridesDefaultStyle se podría establecer como parte del comportamiento nativo para la clase de control, en lugar de establecerse
explícitamente en una instancia del control). Asimismo, para poder admitir las claves implícitas para los escenarios de clase derivada, el
control debe invalidar DefaultStyleKey (todos los controles existentes proporcionados como parte de WPF hacen esto). Para obtener más
información sobre el diseño de estilos, temas y controles, vea Instrucciones para el diseño de controles con estilos.
DataTemplate también tiene una clave implícita. La clave implícita para un objeto DataTemplate es el valor de la propiedad DataType.
DataType también se puede especificar como el nombre del tipo en lugar de hacerlo explícitamente utilizando {x:Type...}. Para obtener
información detallada, vea Información general sobre plantillas de datos.

Vea también
Conceptos
Optimizar el rendimiento: Recursos de aplicación
Recursos y código
Cómo: Definir y hacer referencia a un recurso
Información general sobre la administración de aplicaciones
Extensión de marcado x:Type
Extensión de marcado StaticResource
Extensión de marcado DynamicResource

Referencia
ResourceDictionary

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Windows Presentation Foundation
Información general sobre animaciones
Vea también Enviar comentarios

Windows Presentation Foundation (WPF) proporciona un conjunto eficaz de características de gráficos y diseño que permite crear interfaces
de usuario y documentos atractivos. Las animaciones pueden hacer que una interfaz de usuario sea más vistosa y práctica. Simplemente con
animar un color de fondo o con aplicar un elemento Transform animado, puede crear transiciones de pantalla espectaculares o proporcionar
indicaciones visuales útiles.
Aquí se ofrece una introducción al sistema de animación y temporización de WPF. Se centra en la animación de objetos WPF mediante
guiones gráficos.
Este tema contiene las secciones siguientes.

Introducción a las animaciones


Una animación es una ilusión que se crea mediante el cambio rápido entre una serie de imágenes, cada una de las cuales es ligeramente
diferente de la anterior. El cerebro percibe el grupo de imágenes como una sola escena cambiante. En las películas, esta efecto se
obtiene mediante el uso de cámaras que graban muchas fotografías, o fotogramas, cada segundo. Cuando los fotogramas se reproducen
en un proyector, la audiencia ve una imagen en movimiento.
La animación en un equipo es similar. Por ejemplo, un programa que hace que un dibujo de un rectángulo se desvanezca hasta
desaparecer de la vista podría funcionar de la siguiente manera.
 El programa crea un temporizador.
 El programa comprueba el temporizador en los intervalos establecidos para ver cuánto tiempo ha transcurrido.
 Cada vez que el programa comprueba el temporizador, calcula el valor de opacidad actual del rectángulo en función del tiempo que
ha transcurrido.
 Después, el programa actualiza el rectángulo con el nuevo valor y lo redibuja.
Antes de WPF, los programadores de Microsoft Windows tenían que crear y administrar sus propios sistemas de control de tiempo o
utilizar bibliotecas personalizadas especiales. WPF incluye un sistema del control de tiempo eficaz que se expone a través del código
administrado y Lenguaje de marcado de aplicaciones extensible (XAML), y que está completamente integrado en el marco de trabajo de
WPF. La animación de WPF permite animar controles y otros objetos gráficos de forma sencilla.
WPF controla todo el trabajo de administración del sistema de temporización y de actualización de la pantalla que se produce en
segundo plano. Proporciona clases de control de tiempo que permiten centrarse en los efectos que se desean crear, en lugar de en la
manera de lograr esos efectos. WPF también permite crear fácilmente animaciones propias exponiendo clases base de animación de las
que pueden heredar sus propias clases para generar animaciones personalizadas. Estas animaciones personalizadas se benefician de la
mayoría de las ventajas de rendimiento de las clases de animación estándar.

Sistema de animación de propiedades de WPF


Si conoce algunos conceptos importantes del sistema de temporización, le resultará más fácil usar las animaciones de WPF. Lo más
importante es que, en WPF, los objetos se animan al aplicar animaciones a sus propiedades individuales. Por ejemplo, para hacer que un
elemento de marco crezca, se animan sus propiedades Width y Height. Para hacer que un objeto se desvanezca hasta desaparecer de la
vista, se anima su propiedad Opacity.
Para tener funcionalidad de animación, una propiedad debe cumplir los tres requisitos siguientes:
 Debe ser una propiedad de dependencia.
 Debe pertenecer a una clase que herede de DependencyObject e implemente la interfaz IAnimatable.
 Debe haber un tipo de animación compatible disponible. Si Windows Presentation Foundation (WPF) no proporciona ninguno, puede
crear el suyo propio. Consulte Información general sobre animaciones personalizadas.
WPF contiene muchos objetos con propiedades que se pueden animar. Algunos controles, como Button y TabControl, y también los
objetos Panel y Shape heredan de DependencyObject. La mayoría de sus propiedades son propiedades de dependencia.
Las animaciones pueden usarse casi en cualquier parte, lo que incluye estilos y plantillas de control. Las animaciones no tienen que ser
visuales; puede animar objetos que no formen parte de la interfaz de usuario siempre y cuando cumplan los criterios que se describen
en esta sección.

Ejemplo: Hacer que un elemento se intensifique y se atenúe hasta desaparecer


En este ejemplo se muestra cómo usar una animación de WPF para animar el valor de una propiedad de dependencia. Se usa
DoubleAnimation, que es un tipo de animación que genera valores Double, para animar la propiedad Opacity de un elemento Rectangle.
Como resultado, Rectangle se intensifica y se atenúa hasta desaparecer de la vista.
En la primera parte del ejemplo se crea un elemento Rectangle y se muestra en un objeto Page. Los pasos siguientes muestran cómo
crear una animación y aplicarla a la propiedad Opacity del rectángulo.
Copiar código
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Fading Rectangle Example">
<StackPanel Margin="10">

<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
</Rectangle>
</StackPanel>
</Page>

Copiar código
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Microsoft.SDK.Animation
{
public class RectangleOpacityFadeExample : Page
{
public RectangleOpacityFadeExample()
{
NameScope.SetNameScope(this, new NameScope());
this.WindowTitle = "Fading Rectangle Example";
StackPanel myPanel = new StackPanel();
myPanel.Margin = new Thickness(10);

Rectangle myRectangle = new Rectangle();


myRectangle.Name = "myRectangle";
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = Brushes.Blue;
myPanel.Children.Add(myRectangle);
this.Content = myPanel;
}
}
}

Parte 1: Crear una DoubleAnimation


Una manera de conseguir que un elemento se intensifique y se atenúe hasta desaparecer es animar su propiedad Opacity. Dado que la
propiedad Opacity es de tipo Double, necesita una animación que genere valores double. DoubleAnimation es una animación que se
ajusta a ese perfil. DoubleAnimation crea una transición entre dos valores double. Para especificar el valor inicial, establezca su
propiedad From. Para especificar el valor final, establezca su propiedad To.
1. Un valor de opacidad de 1.0 hace que el objeto sea completamente opaco y un valor de opacidad de 0.0 hace que sea
completamente invisible. Para lograr una transición de la animación de 1.0 a 0.0, establezca su propiedad From en 1.0 y su
propiedad To en 0.0 .
Copiar código
...
<DoubleAnimation From="1.0" To="0.0" />
...
[C#]
Copiar código
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
2. Luego debe especificar un valor Duration. El valor Duration de una animación especifica cuánto tiempo le lleva pasar del valor de
origen al valor de destino. En el ejemplo siguiente, se proporciona a la animación una duración de cinco segundos.
Copiar código
...
<DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" />
...
Copiar código
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
3. En el código anterior se mostraba una animación que cambiaba de 1.0 a 0.0, lo que hacía que el elemento de destino se atenuara y
pasase de ser completamente opaco a ser completamente invisible. Para hacer que el elemento vuelva a intensificarse antes de
desaparecer, establezca la propiedad AutoReverse de la animación en true. Para hacer que la animación se repita indefinidamente,
establezca su propiedad RepeatBehavior en Forever.
Copiar código
...
<DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever"/>
...
Copiar código
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

Parte 2: Crear un guión gráfico


Para aplicar una animación a un objeto, se crea un objeto Storyboard y se usan las propiedades asociadas TargetName y TargetProperty
para especificar el objeto y la propiedad que se desean animar.
1. Cree Storyboard y agregue la animación como su elemento secundario.
Copiar código
...
<Storyboard>
<DoubleAnimation
From="1.0" To="0.0" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
...
En el código, declare Storyboard como un miembro de clase.
Copiar código
public class RectangleOpacityFadeExample : Page
{
private Storyboard myStoryboard;
A continuación, inicialice Storyboard y agregue la animación como su elemento secundario.
Copiar código
myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
2. Storyboard debe saber dónde aplicar la animación. Use la propiedad asociada Storyboard.TargetName para especificar el objeto que
desea animar. En el código siguiente, a DoubleAnimation se le asigna el nombre de destino de MyRectangle, que es el nombre del
objeto que se va a animar.
Copiar código
...
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
From="1.0" To="0.0" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
...
Copiar código
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Nota:
Cuando se crean guiones gráficos en el código, es necesario realizar dos pasos adicionales: crear un ámbito de nombres y
registrar el nombre del objeto que se va a animar. En el código incluido al principio de esta sección para crear la página y el
rectángulo también se declaraba un objeto NameScope y se registraba un nombre para el rectángulo. Use el método
SetNameScope para crear NameScope, si todavía no existe. Use el método RegisterName para registrar el nombre del objeto de
destino con el elemento para el que creó NameScope. De lo contrario, Storyboard no encontrará el objeto para animarlo. Para
obtener otro ejemplo, vea Cómo: Definir un ámbito de nombres.
3. Use la propiedad asociada TargetProperty para especificar la propiedad que desea animar. En el código siguiente, la animación se
configura para tener como destino la propiedad Opacity de Rectangle.
XAML Copiar código
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>

Copiar código
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));
Para obtener más información acerca de la sintaxis de TargetProperty y más ejemplos, vea Información general sobre objetos
Storyboard.

Parte 3 (XAML): Asociar el guión gráfico a un desencadenador


La manera más fácil de aplicar e iniciar un elemento Storyboard en XAML es usar un desencadenador de eventos.
Cree un objeto BeginStoryboard y asóciele su guión gráfico. BeginStoryboard es un tipo de TriggerAction que aplica e inicia Storyboard.
XAML Copiar código
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>

Cree un EventTrigger y agregue BeginStoryboard a su colección Actions. Establezca la propiedad RoutedEvent de EventTrigger en el
evento enrutado que desee para iniciar Storyboard. Para obtener más información acerca de los eventos enrutados, vea Información
general sobre eventos enrutados.
XAML Copiar código
<!-- Animates the rectangle's opacity. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>

Agregue EventTrigger a la colección Triggers del rectángulo.


XAML Copiar código
<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
<Rectangle.Triggers>
<!-- Animates the rectangle's opacity. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

Parte 3 (código): Asociar el guión gráfico a un controlador de eventos


La manera más fácil de aplicar e iniciar un Storyboard en el código es usar un controlador de eventos.
1. Registre el evento Loaded del rectángulo.
[C#]
Copiar código
myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);
2. Declare el controlador de eventos. En el controlador de eventos, use el método Begin para aplicar el guión gráfico.
[C#]
Copiar código
...
public void myRectangleLoaded(object sender, RoutedEventArgs e)
{
myStoryboard.Begin(this);
}
...

Ejemplo completo
En el ejemplo siguiente se muestra el código completo que es necesario para crear un rectángulo que se intensifica y se atenúa hasta
desaparecer.
XAML Copiar código
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Fading Rectangle Example">
<StackPanel Margin="10">
<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
<Rectangle.Triggers>
<!-- Animates the rectangle's opacity. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</StackPanel>
</Page>

C# Copiar código
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace SDKSample
{

public class RectangleOpacityFadeExample : Page


{
private Storyboard myStoryboard;

public RectangleOpacityFadeExample()
{
NameScope.SetNameScope(this, new NameScope());

this.WindowTitle = "Fading Rectangle Example";


StackPanel myPanel = new StackPanel();
myPanel.Margin = new Thickness(10);

Rectangle myRectangle = new Rectangle();


myRectangle.Name = "myRectangle";
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = Brushes.Blue;

DoubleAnimation myDoubleAnimation = new DoubleAnimation();


myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

myStoryboard = new Storyboard();


myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));

// Use the Loaded event to start the Storyboard.


myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);

myPanel.Children.Add(myRectangle);
this.Content = myPanel;
}

public void myRectangleLoaded(object sender, RoutedEventArgs e)


{
myStoryboard.Begin(this);
}

}
}

Tipos de animación
Dado que las animaciones generan valores de propiedad, existen distintos tipos de animaciones para los diversos tipos de propiedades.
Para animar una propiedad que acepta una estructura Double, como la propiedad Width de un elemento, se usa una animación que
genera valores Double. Para animar una propiedad que acepta una estructura Point, se usa una animación que genera valores Point; y
así sucesivamente. Dado que existen tipos de propiedades diferentes, hay varias clases de animación en el espacio de nombres
System.Windows.Media.Animation. Afortunadamente se rigen por una convención de nomenclatura estricta que hace que sea fácil
diferenciarlas:
 <Tipo>Animation
Conocidas como animaciones "From/To/By" o "basic", generan una animación entre un valor inicial y de destino o agregan un valor de
desplazamiento al valor inicial.
 Para especificar un valor inicial, establezca la propiedad From de la animación.
 Para especificar un valor final, establezca la propiedad To de la animación.
 Para especificar un valor de desplazamiento, establezca la propiedad By de la animación.
En los ejemplos de este tema se incluyen estas animaciones porque son las más fáciles de usar. Las animaciones From/To/By se
describen en detalle en Información general sobre animaciones From/To/By.
 <<Tipo>AnimationUsingKeyFrames
Las animaciones de fotogramas clave son más eficaces que las animaciones From/To/By porque se puede especificar cualquier
número de valores de destino e incluso controlar su método de interpolación. Algunos tipos solo se pueden animar con animaciones
de fotogramas clave. Las animaciones de fotogramas clave se describen con detalle en Información general sobre animaciones de
fotogramas clave.
 <<Tipo>AnimationUsingPath
Las animaciones de trazado permiten usar un trazado geométrico para generar valores animados.
 <<Tipo>AnimationBase
Clase abstracta que, cuando se implementa, anima un valor de <Tipo>. Esta clase actúa como clase base para las clases
<Tipo>Animation y <Tipo>AnimationUsingKeyFrames. Tiene que tratar directamente con estas clases solo si desea crear sus propias
animaciones personalizadas. En caso contrario, use <Tipo>Animation o KeyFrame<Tipo>Animation.
En la mayoría de los casos, deseará usar las clases <Tipo>Animation, como DoubleAnimation y ColorAnimation.
La tabla siguiente muestra varios tipos de animación comunes y algunas propiedades con las que se usan.

Tipo de Animación básica Animación de fotogramas clave Animación de trazado Ejemplo de uso
propiedad correspondiente correspondiente correspondiente
(From/To/By)

Color ColorAnimation ColorAnimationUsingKeyFrames Ninguna Animar la propiedad


Color de un objeto
SolidColorBrush o
GradientStop.

Double DoubleAnimation DoubleAnimationUsingKeyFrames DoubleAnimationUsingPath Animar la propiedad


Width de un objeto
DockPanel o la propiedad
Height de un objeto
Button.

Point PointAnimation PointAnimationUsingKeyFrames PointAnimationUsingPath Animar la posición


Center de un objeto
EllipseGeometry.

String Ninguna StringAnimationUsingKeyFrames Ninguna Animar la propiedad Text


de un objeto TextBlock o
la propiedad Content de
un objeto Button.

Las animaciones son escalas de tiempo


Todos los tipos de animaciones heredan de la clase Timeline, por lo que todas las animaciones son tipos de escalas de tiempo
especializados. Un objeto Timeline define un segmento de tiempo. Puede especificar los comportamientos de temporización de una
escala de tiempo: su Duration, cuántas veces se repite e incluso con qué rapidez pasa el tiempo para ella.
Dado que una animación es un objeto Timeline, también representa un segmento de tiempo. Una animación también calcula los valores
de salida a medida que avanza por su segmento de tiempo (o Duration). A medida que la animación avanza, o se "reproduce", actualiza
la propiedad a la que está asociada.
Tres propiedades de temporización que se usan con frecuencia son Duration, AutoReverse y RepeatBehavior.

Propiedad Duration
Como se ha mencionado previamente, una escala de tiempo representa un segmento de tiempo. La propiedad Duration de la escala de
tiempo, que normalmente se especifica mediante un valor TimeSpan, determina la longitud de ese segmento. Cuando una escala de
tiempo llega al final de su duración, ha completado una iteración.
Una animación usa su propiedad Duration para determinar su valor actual. Si no especifica un valor Duration para una animación, se usa
1 segundo, que es el valor predeterminado.
La sintaxis siguiente muestra una versión simplificada de la sintaxis de atributo de Lenguaje de marcado de aplicaciones extensible
(XAML) para la propiedad Duration.

horas : minutes : seconds

La tabla siguiente muestra varias configuraciones de Duration y sus valores resultantes.

Configuración Valor resultante

0:0:5.5 5,5 segundos.

0:30:5.5 30 minutos y 5,5 segundos.

1:30:5.5 1 hora, 30 minutos y 5,5 segundos.

Una manera de especificar Duration en el código es usar el método FromSeconds para crear un elemento TimeSpan y después declarar
una nueva estructura Duration mediante TimeSpan.
Para obtener más información acerca de los valores de Duration y la sintaxis de Lenguaje de marcado de aplicaciones extensible (XAML)
completa, vea la página del tipo Duration.

AutoReverse
La propiedad AutoReverse especifica si una escala de tiempo se vuelve a reproducir hacia atrás al llegar al final de Duration. Si establece
esta propiedad de animación en true, la animación se invierte después de llegar al fin de Duration y se reproduce desde su valor final
hasta su valor inicial. De forma predeterminada, esta propiedad es false.

RepeatBehavior
La propiedad RepeatBehavior especifica cuántas veces se reproduce una escala de tiempo. De forma predeterminada, las escalas de
tiempo tienen una iteración de 1.0, lo que significa que se reproducen una vez y no se repiten en absoluto.
Para obtener más información acerca de estas propiedades y otras, vea Información general sobre comportamientos de control de
tiempo.

Aplicar una animación a una propiedad


En las secciones anteriores se han descrito los distintos tipos de animaciones y sus propiedades de temporización. En esta sección se
muestra cómo aplicar la animación a la propiedad que se desea animar. Los objetos Storyboard proporcionan una manera de aplicar
animaciones a propiedades. Storyboard es una escala de tiempo contenedora que proporciona información de destino para las
animaciones que contiene.

Objetos y propiedades de destino


La clase Storyboard proporciona las propiedades asociadas TargetName y TargetProperty. Al establecer estas propiedades en una
animación, se indica a la animación qué debe animar. Sin embargo, para que una animación pueda tener un objeto como destino,
normalmente se debe dar un nombre al objeto.
Asignar un nombre a un FrameworkElement difiere de asignar un nombre a un objeto Freezable. La mayoría de los controles y paneles
son elementos de marco, pero los objetos gráficos más puros, como los pinceles, las transformaciones y las formas geométricas, son
objetos inmovilizables. Si no tiene la certeza de si un tipo es FrameworkElement o Freezable, consulte la sección Jerarquía de
herencia de la página del tipo.
 Para convertir un FrameworkElement en un destino de animación, se le asigna un nombre mediante el establecimiento de su
propiedad Name. En el código también se debe usar el método RegisterName para registrar el nombre del elemento con la página a la
que pertenece.
 Para convertir un objeto Freezable en un destino en XAML, se usa el Atributo x:Name para asignarle un nombre. En el código
simplemente se usa el método RegisterName para registrar el objeto con la página a la que pertenece.
En las secciones siguientes se proporciona un ejemplo de cómo asignar un nombre a un elemento en XAML y en el código. Para obtener
información más detallada acerca de la asignación de nombres y destinos, vea Información general sobre objetos Storyboard.

Aplicar e iniciar guiones gráficos


Para iniciar un guión gráfico en XAML, se asocia a un EventTrigger. Un EventTrigger es un objeto que describe qué acciones deben
realizarse cuando se produce un evento especificado. Una de esas acciones puede ser una acción BeginStoryboard, que se usa para
iniciar el guión gráfico. Los desencadenadores de eventos son similares en concepto a los controladores de eventos, porque permiten
especificar cómo responde una aplicación a un evento determinado. A diferencia de los controladores de eventos, los desencadenadores
de eventos se pueden describir totalmente en XAML; no se requiere ningún otro código.
Para iniciar un Storyboard en el código, se puede usar EventTrigger o el método Begin de la clase Storyboard.

Control interactivo de guiones gráficos


En el ejemplo anterior se mostró cómo iniciar Storyboard cuando se produce un evento. Un Storyboard también se puede controlar
interactivamente después haberse iniciado: puede pausar, reanudar, detener, hacer que avance hasta su período de relleno, buscar y
quitar el Storyboard. Para obtener más información y un ejemplo que muestra cómo controlar interactivamente un Storyboard, vea
Información general sobre objetos Storyboard.

Comportamiento tras la finalización de una animación


La propiedad FillBehavior especifica cómo se comporta una escala de tiempo cuando finaliza. De forma predeterminada, una escala de
tiempo inicia el proceso Filling cuando finaliza. Una animación que se encuentra en el proceso Filling mantiene su valor de salida final.
El objeto DoubleAnimation del ejemplo anterior no finaliza porque su propiedad RepeatBehavior está establecida en Forever. En el
ejemplo siguiente se anima un rectángulo mediante el uso de una animación similar. A diferencia del ejemplo anterior, las propiedades
RepeatBehavior y AutoReverse de esta animación se mantienen en sus valores predeterminados. Por consiguiente, la animación
progresa de 1 a 0 en cinco segundos y, a continuación, se detiene.
XAML Copiar código
<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
<Rectangle.Triggers>

<!-- Animates the rectangle's opacity. -->


<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>

C# Copiar código
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));

Dado que no se modificó el valor predeterminado de su FillBehavior, que es HoldEnd, la animación mantiene su valor final, 0, cuando
finaliza. Por tanto, la propiedad Opacity del rectángulo se mantiene en 0 después de que finaliza la animación. Si establece la propiedad
Opacity del rectángulo en otro valor, aparentemente su código no tiene ningún efecto, porque la animación todavía influye en la
propiedad Opacity.
Una manera de recobrar el control de una propiedad animada en el código es usar el método BeginAnimation y especificar null para el
parámetro AnimationTimeline. Para obtener más información y un ejemplo, vea Cómo: Establecer una propiedad después de animarla
con un guión gráfico.
Tenga en cuenta que, aunque parece que no tiene ningún efecto establecer un valor de una propiedad que tiene una animación Active o
Filling, el valor de la propiedad realmente cambia. Para obtener más información, vea Información general sobre sistemas de
temporización y animación.

Animaciones con enlace de datos y animaciones animadas


La mayoría de las propiedades de animación pueden ser enlazadas a datos o animadas; por ejemplo, puede animar la propiedad
Duration de DoubleAnimation. Sin embargo, debido a la manera en que funciona el sistema de temporización, las animaciones enlazadas
a datos o animadas no se comportan como los demás objetos enlazados a datos o animados. Para entender su comportamiento, le será
útil comprender el significado de aplicar una animación a una propiedad.
Consulte el ejemplo de la sección anterior que mostraba cómo animar la propiedad Opacity de un rectángulo. Cuando se carga el
rectángulo del ejemplo anterior, su desencadenador de eventos aplica el elemento Storyboard. El sistema de temporización crea una
copia de Storyboard y de su animación. Estas copias se inmovilizan (se convierten en copias de sólo lectura) y a partir de ellas se crean
objetos Clock. Estos relojes son los que realmente se encargan de animar las propiedades de destino.
El sistema de temporización crea un reloj para DoubleAnimation y lo aplica al objeto y a la propiedad que se especifican mediante las
propiedades TargetName y TargetProperty de DoubleAnimation. En este caso, el sistema de temporización aplica el reloj a la propiedad
Opacity del objeto denominado "MyRectangle".
Aunque también se crea un reloj para Storyboard, el reloj no se aplica a ninguna propiedad. Su finalidad es controlar a su reloj
secundario, el creado para DoubleAnimation.
Para que una animación refleje cambios de enlace de datos o de animación, su reloj se debe regenerar. Los relojes no se regeneran
automáticamente. Para que una animación refleje los cambios, vuelva a aplicar su guión gráfico mediante un elemento BeginStoryboard
o el método Begin. Al usar cualquiera de estos métodos, la animación se reinicia. En el código, puede usar el método Seek para hacer
que el guión gráfico regrese a su posición anterior.
Para obtener un ejemplo de una animación enlazada a datos, vea Ejemplo Key Spline Animation. Para obtener más información acerca
del funcionamiento del sistema de animación y temporización, vea Información general sobre sistemas de temporización y animación.

Otras maneras de crear animaciones


Los ejemplos de este tema muestran cómo aplicar animaciones mediante guiones gráficos. En el código se pueden aplicar animaciones
de otras maneras. Para obtener más información, vea Información general sobre técnicas de animación de propiedades.

Ejemplos de animaciones
Los ejemplos siguientes pueden ayudarle a familiarizarse con la forma de agregar animaciones a sus aplicaciones.
 Ejemplo Property Animation
Muestra cómo aplicar animaciones a elementos de marco y a objetos inmovilizables.
 Ejemplo From, To, and By Animation Target Values
Muestra distintas configuraciones From/To/By.
 Ejemplo Animation Timing Behavior
Muestra las distintas maneras de controlar el comportamiento de temporización de una animación. Este ejemplo también muestra
cómo enlazar a datos el valor de destino de una animación.

Vea también
Conceptos
Información general sobre animaciones From/To/By
Información general sobre animaciones de fotogramas clave
Información general sobre objetos Storyboard
Información general sobre comportamientos de control de tiempo
Información general sobre sistemas de temporización y animación
Información general sobre eventos de control de tiempo
Información general sobre Windows Presentation Foundation

Referencia
Timeline
Storyboard

Enviar comentarios sobre este tema a Microsoft.


Contraer todo Código: Todos
Windows Presentation Foundation
Tutorial: Crear un botón mediante el uso de XAML
Vea también Enviar comentarios

El objetivo de este tutorial es aprender a crear un botón animado para usarlo en una aplicación Windows Presentation Foundation (WPF).
Este tutorial utiliza estilos y una plantilla para crear un recurso de botón personalizado que permite la reutilización de código y la separación
de la lógica del botón de la declaración del botón. Este tutorial está escrito completamente en Lenguaje de marcado de aplicaciones
extensible (XAML).
Nota importante:
Este tutorial sirve como guía en los pasos necesarios para crear la aplicación escribiendo, o copiando y pegando Lenguaje de marcado
de aplicaciones extensible (XAML) en Microsoft Visual Studio. Si prefiere aprender a usar una herramienta de diseño (Microsoft
Expression Blend) para crear la misma aplicación, vea Tutorial: Crear un botón mediante Microsoft Expression Blend.
La figura siguiente muestra los botones acabados.

Crear botones básicos


Empecemos por crear un nuevo proyecto y agregar unos botones a la ventana.

Para crear un nuevo proyecto de WPF y agregar botones a la ventana


1. Inicie Visual Studio.
2. Cree un nuevo proyecto de WPF: En el menú Archivo, señale a Nuevo y, a continuación, haga clic en Proyecto. Se abre la
ventana que se muestra en la ilustración siguiente. En el panel de la izquierda, bajo el nodo Visual C#, seleccione .NET
Framework 3.0. En el panel de la derecha, seleccione la plantilla Aplicación para Windows (WPF). Llame al proyecto
"AnimatedButton". Esto creará el esqueleto para la aplicación.

3. Agregue los botones predeterminados básicos: la plantilla proporciona todos los archivos que necesita para este tutorial. Abra
el archivo Window1.xaml haciendo doble clic en él en el Explorador de soluciones. De forma predeterminada, hay un elemento Grid
en Window1.xaml. Quite el elemento Grid y agregue unos botones a la página Lenguaje de marcado de aplicaciones extensible
(XAML) escribiendo o copiando y pegando el siguiente código resaltado en Window1.xaml:
Copiar código
<Window x:Class="AnimatedButton.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AnimatedButton" Height="300" Width="300"
Background="Black">

<!-- Buttons arranged vertically inside a StackPanel. -->


<StackPanel HorizontalAlignment="Left">
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>

</Window>
Presione F5 para ejecutar la aplicación; debería ver un conjunto de botones parecido a la ilustración siguiente.

Ahora que ha creado los botones básicos, ha terminado de trabajar en el archivo Window1.xaml. El resto del tutorial se centra en el
archivo app.xaml, definiendo estilos y una plantilla para los botones.

Establecer propiedades básicas


A continuación, establezcamos algunas propiedades de estos botones para controlar su aspecto y su diseño. En lugar de establecer
individualmente las propiedades de los botones, utilizará recursos para definir las propiedades de botón de toda la aplicación. Los
recursos de aplicación son conceptualmente similares a Hojas de estilos en cascada (CSS) externas para páginas web; sin embargo, los
recursos son mucho más eficaces que Hojas de estilos en cascada (CSS), como verá al final de este tutorial. Para obtener más
información sobre los recursos, vea Información general sobre recursos.

Para utilizar estilos para establecer propiedades básicas en los botones


1. Defina un bloque Application.Resources: abra app.xaml y agregue el marcado resaltado siguiente si aún no está allí:
Copiar código
<Application x:Class="AnimatedButton.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml"
>
<Application.Resources>

<!-- Resources for the entire application can be


defined here. -->

</Application.Resources>
</Application>
El ámbito del recurso lo determina dónde se defina el recurso. Definir recursos en Application.Resoureses en el archivo app.xaml
permite utilizar el recurso en cualquier parte de la aplicación. Para obtener más información sobre cómo definir el ámbito de los
recursos, vea Información general sobre recursos.
2. Cree un estilo y defina los valores de las propiedades básicas con él: agregue el marcado siguiente al bloque
Application.Resources. Este marcado crea un objeto Style que se aplica a todos los botones de la aplicación, estableciendo la
propiedad Width de los botones en 90 y Margin en 10:
Copiar código
<Application.Resources>

<Style TargetType="Button">
<Setter Property="Width" Value="90" />
<Setter Property="Margin" Value="10" />
</Style>

</Application.Resources>
La propiedad TargetType especifica que el estilo se aplica a todos los objetos de tipo Button. Cada Setter establece un valor de la
propiedad diferente para el objeto Style. Por consiguiente, en este punto cada botón de la aplicación tiene un ancho de 90 y un
margen de 10. Si presiona F5 para ejecutar la aplicación, verá la ventana siguiente.
Hay mucho más que puede hacer con estilos, incluidas diversas maneras de ajustar con precisión a qué objetos se destinan,
especificar valores de propiedad complejos e incluso utilizar estilos como entrada para otros estilos. Para obtener más información,
vea Styling and Templating Overview.
3. Establezca un valor de propiedad de estilo en un recurso: los recursos permiten reutilizar fácilmente objetos y valores que se
definen con frecuencia. Es especialmente útil definir valores complejos utilizando recursos, para hacer el código más modular.
Agregue el marcado resaltado siguiente a app.xaml.
Copiar código
<Application.Resources>

<LinearGradientBrush x:Key="GrayBlueGradientBrush"
StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="DarkGray" Offset="0" />
<GradientStop Color="#CCCCFF" Offset="0.5" />
<GradientStop Color="DarkGray" Offset="1" />
</LinearGradientBrush>

<Style TargetType="{x:Type Button}">


<Setter Property="Background"
Value="{StaticResource GrayBlueGradientBrush}" />
<Setter Property="Width" Value="80" />
<Setter Property="Margin" Value="10" />
</Style>

</Application.Resources>
Directamente bajo el bloque Application.Resources, creó un recurso llamado "GrayBlueGradientBrush". Este recurso define un
degradado horizontal. Este recurso se puede utilizar en cualquier parte de la aplicación como un valor de propiedad, incluso dentro
del establecedor de estilo del botón para la propiedad Background. Ahora, todos los botones tienen un valor de propiedad
Background de este degradado.
Presione F5 para ejecutar la aplicación. Debe tener este aspecto:

Crear una plantilla que define la apariencia del botón


En esta sección creará una plantilla que personaliza la apariencia (presentación) del botón. La presentación del botón se compone de
varios objetos, que incluyen rectángulos y otros componentes para dar una apariencia única al botón.
Hasta ahora, el control de la apariencia de los botones de la aplicación se ha confinado a cambiar propiedades del botón. ¿Qué ocurre si
desea realizar cambios más radicales en la apariencia del botón? Las plantillas permiten un control eficaz sobre la presentación de un
objeto. Dado que las plantillas se pueden utilizar dentro de estilos, puede aplicar una plantilla a todos los objetos a los que se aplica el
estilo (en este tutorial, el botón).

Para utilizar la plantilla para definir la apariencia del botón


1. Configure la plantilla: dado que los controles como Button tienen una propiedad Template, puede definir el valor de la propiedad
de la plantilla igual que los demás valores de propiedades que hemos establecido en un objeto Style, utilizando un objeto Setter.
Agregue el marcado resaltado siguiente al estilo de botón.
Copiar código
<Application.Resources>

<LinearGradientBrush x:Key="GrayBlueGradientBrush"
StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="DarkGray" Offset="0" />
<GradientStop Color="#CCCCFF" Offset="0.5" />
<GradientStop Color="DarkGray" Offset="1" />
</LinearGradientBrush>

<Style TargetType="{x:Type Button}">


<Setter Property="Background" Value="{StaticResource GrayBlueGradientBrush}" />
<Setter Property="Width" Value="80" />
<Setter Property="Margin" Value="10" />
<Setter Property="Template">
<Setter.Value>
<!-- The button template is defined here. -->
</Setter.Value>
</Setter>
</Style>

</Application.Resources>
2. Modifique la presentación del botón: en este punto, debe definir la plantilla. Agregue el siguiente marcado resaltado: Este
marcado especifica dos elementos Rectangle con bordes redondeados, seguidos por un control DockPanel. El control DockPanel se
utiliza para hospedar el objeto ContentPresenter del botón. Un objeto ContentPresenter muestra el contenido del botón. En este
tutorial, el contenido es texto ("Button 1", "Button 2", "Button 3"). Todos los componentes de la plantilla (los rectángulos y el control
DockPanel) se disponen en el interior de un control Grid.
Copiar código
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}" ClipToBounds="True">

<!-- Outer Rectangle with rounded corners. -->


<Rectangle x:Name="outerRectangle"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Stroke="{TemplateBinding Background}"
RadiusX="20" RadiusY="20" StrokeThickness="5"
Fill="Transparent" />

<!-- Inner Rectangle with rounded corners. -->


<Rectangle x:Name="innerRectangle"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="Transparent"
StrokeThickness="20"
Fill="{TemplateBinding Background}"
RadiusX="20" RadiusY="20" />

<!-- Present Content (text) of the button. -->


<DockPanel Name="myContentPresenterDockPanel">
<ContentPresenter x:Name="myContentPresenter" Margin="20"
Content="{TemplateBinding Content}"
TextBlock.Foreground="Black" />
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
Presione F5 para ejecutar la aplicación.
1. Agregue un efecto de vidrio a la plantilla: a continuación agregará el vidrio. Primero cree algunos recursos que creen un efecto
de degradado de vidrio. Agregue estos recursos de degradado en cualquier punto del bloque Application.Resources:
Copiar código
<Application.Resources>
<GradientStopCollection x:Key="MyGlassGradientStopsResource">
<GradientStop Color="WhiteSmoke" Offset="0.2" />
<GradientStop Color="Transparent" Offset="0.4" />
<GradientStop Color="WhiteSmoke" Offset="0.5" />
<GradientStop Color="Transparent" Offset="0.75" />
<GradientStop Color="WhiteSmoke" Offset="0.9" />
<GradientStop Color="Transparent" Offset="1" />
</GradientStopCollection>

<LinearGradientBrush x:Key="MyGlassBrushResource"
StartPoint="0,0" EndPoint="1,1" Opacity="0.75"
GradientStops="{StaticResource MyGlassGradientStopsResource}" />
<!-- Styles and other resources below here. -->
Estos recursos se utilizan como propiedad Fill para un rectángulo que insertamos en el control Grid de la plantilla de botón. Agregue
el siguiente marcado resaltado a la plantilla.
Copiar código
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"
ClipToBounds="True">

<!-- Outer Rectangle with rounded corners. -->


<Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />

<!-- Inner Rectangle with rounded corners. -->


<Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20"
Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" />

<!-- Glass Rectangle -->


<Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0"
Fill="{StaticResource MyGlassBrushResource}"
RenderTransformOrigin="0.5,0.5">
<Rectangle.Stroke>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="LightBlue" />
<GradientStop Offset="1.0" Color="Gray" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Stroke>

<!-- These transforms have no effect as they are declared here.


The reason the transforms are included is to be targets
for animation (see later). -->
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform />
<RotateTransform />
</TransformGroup>
</Rectangle.RenderTransform>

<!-- A BevelBitmapEffect is applied to give the button a


"Beveled" look. -->
<Rectangle.BitmapEffect>
<BevelBitmapEffect />
</Rectangle.BitmapEffect>
</Rectangle>

<!-- Present Text of the button. -->


<DockPanel Name="myContentPresenterDockPanel">
<ContentPresenter x:Name="myContentPresenter" Margin="20"
Content="{TemplateBinding Content}" TextBlock.Foreground="Black" />
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
Observe que la propiedad Opacity del rectángulo con la propiedad x:Name de "glassCube" es 0, por lo que al ejecutar el ejemplo no
verá el rectángulo de vidrio superpuesto. Esto se debe a que agregaremos después a la plantilla los desencadenadores para cuando
el usuario interactúe con el botón. Sin embargo, puede ver la apariencia que tiene ahora el botón cambiando el valor Opacity a 1 y
ejecutando la aplicación. Vea la ilustración siguiente. Antes de continuar con el paso siguiente, vuelva a establecer Opacity en 0.

Crear la interactividad del botón


En esta sección, creará desencadenadores de propiedad y desencadenadores de evento para cambiar valores de propiedad y ejecutar
animaciones en respuesta a acciones del usuario tales como mover el puntero del mouse sobre el botón y hacer clic.
Una manera fácil de agregar interactividad (entrada de mouse, salida de mouse, clic, etc.) es definir los desencadenadores dentro de la
plantilla o del estilo. Para crear un objeto Trigger, defina una propiedad "condición" tal como: el valor de la propiedad IsMouseOver del
botón es igual a true. A continuación, defina establecedores (acciones) que tengan lugar cuando la condición de activación sea
verdadera.

Para crear la interactividad del botón


1. Agregue desencadenadores de plantilla: agregue el marcado resaltado a la plantilla.
Copiar código
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}" ClipToBounds="True">

<!-- Outer Rectangle with rounded corners. -->


<Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />

<!-- Inner Rectangle with rounded corners. -->


<Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="Transparent"
StrokeThickness="20"
Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20"
/>

<!-- Glass Rectangle -->


<Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0"
Fill="{StaticResource MyGlassBrushResource}"
RenderTransformOrigin="0.5,0.5">
<Rectangle.Stroke>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="LightBlue" />
<GradientStop Offset="1.0" Color="Gray" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Stroke>

<!-- These transforms have no effect as they


are declared here.
The reason the transforms are included is to be targets
for animation (see later). -->
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform />
<RotateTransform />
</TransformGroup>
</Rectangle.RenderTransform>

<!-- A BevelBitmapEffect is applied to give the button a


"Beveled" look. -->
<Rectangle.BitmapEffect>
<BevelBitmapEffect />
</Rectangle.BitmapEffect>
</Rectangle>

<!-- Present Text of the button. -->


<DockPanel Name="myContentPresenterDockPanel">
<ContentPresenter x:Name="myContentPresenter" Margin="20"
Content="{TemplateBinding Content}" TextBlock.Foreground="Black" />
</DockPanel>
</Grid>

<ControlTemplate.Triggers>
<!-- Set action triggers for the buttons and define
what the button does in response to those triggers. -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
2. Agregue desencadenadores de propiedad: agregue el marcado resaltado al bloque ControlTemplate.Triggers:
Copiar código
<ControlTemplate.Triggers>

<!-- Set properties when mouse pointer is over the button. -->
<Trigger Property="IsMouseOver" Value="True">

<!-- Below are three property settings that occur when the
condition is met (user mouses over button). -->
<!-- Change the color of the outer rectangle when user
mouses over it. -->
<Setter Property ="Rectangle.Stroke" TargetName="outerRectangle"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />

<!-- Sets the glass opacity to 1, therefore, the


glass "appears" when user mouses over it. -->
<Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />

<!-- Makes the text slightly blurry as though you


were looking at it through blurry glass. -->
<Setter Property="ContentPresenter.BitmapEffect"
TargetName="myContentPresenter">
<Setter.Value>
<BlurBitmapEffect Radius="1" />
</Setter.Value>
</Setter>
</Trigger>

<ControlTemplate.Triggers/>
Presione F5 para ejecutar la aplicación y ver el efecto al pasar el puntero del mouse sobre los botones.
3. Agregue un desencadenador de foco: a continuación, agregaremos algunos establecedores similares para administrar el caso en
el que el botón tenga el foco (por ejemplo, después de que el usuario haga clic en él).
Copiar código
<ControlTemplate.Triggers>

<!-- Set properties when mouse pointer is over the button. -->
<Trigger Property="IsMouseOver" Value="True">

<!-- Below are three property settings that occur when the
condition is met (user mouses over button). -->
<!-- Change the color of the outer rectangle when user mouses over it. -->
<Setter Property ="Rectangle.Stroke" TargetName="outerRectangle"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />

<!-- Sets the glass opacity to 1, therefore, the glass "appears" when user mouses over it. -->
<Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />

<!-- Makes the text slightly blurry as though you were looking at it through blurry glass. -->
<Setter Property="ContentPresenter.BitmapEffect" TargetName="myContentPresenter">
<Setter.Value>
<BlurBitmapEffect Radius="1" />
</Setter.Value>
</Setter>
</Trigger>
<!-- Set properties when button has focus. -->
<Trigger Property="IsFocused" Value="true">
<Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />
<Setter Property="Rectangle.Stroke" TargetName="outerRectangle"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
<Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />
</Trigger>

</ControlTemplate.Triggers>
Presione F5 para ejecutar la aplicación y haga clic en uno de los botones. Observa que el botón permanece resaltado después de
hacer clic en él, porque todavía tiene el foco. Si hace clic en otro botón, el nuevo botón obtendrá el foco mientras el último lo pierde.
4. Agregue animaciones para MouseEnter yMouseLeave: a continuación agregamos algunas animaciones a los desencadenadores.
Agregue el marcado siguiente en cualquier punto del bloque ControlTemplate.Triggers.
Copiar código
<!-- Animations that start when mouse enters and leaves button. -->
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard Name="mouseEnterBeginStoryboard">
<Storyboard>

<!-- This animation makes the glass rectangle shrink in the X direction. -->
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
By="-0.1" Duration="0:0:0.5" />

<!-- This animation makes the glass rectangle shrink in the Y direction. -->
<DoubleAnimation
Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
By="-0.1" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>

<!-- Stopping the storyboard sets all animated properties back to default. -->
<StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard" />
</EventTrigger.Actions>
</EventTrigger>
El rectángulo de vidrio se reduce cuando el puntero del mouse pasa sobre el botón y vuelve al tamaño normal cuando el puntero
sale.
Hay dos animaciones que se desencadenan cuando el puntero pasa sobre el botón (cuando se provoca el evento MouseEnter). Estas
animaciones reducen el rectángulo de vidrio a lo largo de los ejes X e Y. Observe las propiedades de los elementos DoubleAnimation,
Duration y By. La propiedad Duration especifica que la animación se produce durante medio segundo, y By especifica que el vidrio
se reduce un 10%.
El segundo desencadenador de eventos (MouseLeave) detiene simplemente el primero. Al detener un objeto Storyboard, todas las
propiedades animadas vuelven a sus valores predeterminados. Por consiguiente, cuando el usuario saca el puntero del botón, el
botón vuelve a ser como era antes de que el puntero del mouse pasara sobre el botón. Para obtener más información acerca de las
animaciones, vea Información general sobre animaciones.
5. Agregue una animación para cuando se haga clic en el botón: el paso final es agregar un desencadenador para cuando el
usuario haga clic en el botón. Agregue el marcado siguiente en cualquier punto del bloque ControlTemplate.Triggers.
Copiar código
<!-- Animation fires when button is clicked, causing glass to spin. -->
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)"
By="360" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
Presione F5 para ejecutar la aplicación y haga clic en uno de los botones. Al hacer clic en un botón, el rectángulo de vidrio gira sobre
sí mismo.

Resumen
En este tutorial, ha realizado los siguientes ejercicios:
 Ha destinado un objeto Style a un tipo de objeto (Button).
 Ha controlado propiedades básicas de los botones en toda la aplicación utilizando el objeto Style.
 Ha creado recursos tales como degradados para utilizarlos para valores de propiedades de los establecedores de Style.
 Ha personalizado la apariencia de botones de toda la aplicación aplicando una plantilla a los botones.
 Ha personalizado el comportamiento de los botones en respuesta a acciones del usuario (tales como MouseEnter, MouseLeave y Click)
incluyendo efectos de animación.

Vea también
Conceptos
Tutorial: Crear un botón mediante Microsoft Expression Blend
Styling and Templating Overview
Información general sobre animaciones
Información general sobre el dibujo con colores sólidos y degradados
Información general sobre efectos de mapa de bits

Enviar comentarios sobre este tema a Microsoft.

Вам также может понравиться