Beruflich Dokumente
Kultur Dokumente
INDICE GENERAL
4. Controles
4.1. Informacin General sobre Controles
4.2. Tutorial: Crear un Botn Animado mediante el uso de XAML
4.3. Personalizacin de Controles
4.3.1. Informacin General sobre la Creacin de Controles
4.3.2. Instrucciones para el Diseo de Controles con Estilos
4.3.3. Adornos
4.3.3.1. Informacin General sobre Adornos
4.3.3.2. Temas Cmo de Adornos
4.3.3.2.1. Cmo: Implementar un Adorno
4.3.3.2.2 Cmo: Enlazar un Adorno a un Elemento
4.3.3.2.3. Cmo: Incluir Adornos en los Elementos Secundarios de un
Panel
4.3.3.2.4. Cmo: Quitar un Adorno de un Elemento
4.3.3.2.5. Cmo: Quitar Todos los Adornos de un Elemento
4.3.4. Ejemplos de ControlTemplate
4.3.4.1. Ejemplo de ControlTemplate de Button
4.3.4.2. Ejemplo de ControlTemplate de CheckBox
4.3.4.3. Ejemplo de ControlTemplate de ComboBox
4.3.4.4. Ejemplo de ControlTemplate de ComboBoxItem
4.3.4.5. Ejemplo de ControlTemplate de ContextMenu
4.3.4.6. Ejemplo de ControlTemplate para DocumentViewer
4.3.4.8. Ejemplo de ControlTemplate de Frame
4.3.4.9. Ejemplo de ControlTemplate de GroupBox
4.3.4.10. Ejemplo de ControlTemplate de Label
4.3.4.11. Ejemplo de ControlTemplate de ListBox
4.3.4.12. Ejemplo de ControlTemplate de ListBoxItem
4.3.4.13. Ejemplo de ControlTemplate de ListView
4.3.4.14. Ejemplo de ControlTemplate de ListViewItem
4.3.4.15. Ejemplo de ControlTemplate de Menu
4.3.4.16. Ejemplo de ControlTemplate para MenuItem
4.3.4.17. Ejemplo de ControlTemplate de NavigationWindow
4.3.4.18. Ejemplo de ControlTemplate para ProgressBar
4.3.4.19. Ejemplo de ControlTemplate de RadioButton
4.3.4.20. Ejemplo de ControlTemplate de ScrollBar
4.3.4.21. Ejemplo de ControlTemplate de ScrollViewer
4.3.4.22. Ejemplo de ControlTemplate de Slider
4.3.4.23. Ejemplo de ControlTemplate de StatusBar
4.3.4.24. Ejemplo de ControlTemplate de TabControl
4.3.4.25. Ejemplo de ControlTemplate de TabItem
4.3.4.26. Ejemplo de ControlTemplate de TextBox
4.3.4.27. Ejemplo de ControlTemplate de ToolBar
4.3.4.28. Ejemplo de ControlTemplate de ToolTip
4.3.4.29. Ejemplo de ControlTemplate de TreeView
4.3.4.30. Ejemplo de ControlTemplate para TreeViewItem
4.3.4.31. Ejemplo de ControlTemplate de Window
4.3.5. Automatizacin de la Interfaz de Usuario de un Control Personalizado de WPF
4.4. Agrupar Controles por Categora
4.5. Modelos de Contenido
4.5.1. Modelo de Contenido de WPF
4.5.2. Informacin General sobre el Modelo de Contenido de Controles
4.5.3. Informacin General sobre el Modelo de Contenido de Decorador
4.5.4. Informacin General sobre el Modelo de Contenido de Paneles
4.5.5. Informacin General sobre el Modelo de Contenido de TextBlock
4.5.6. Informacin General sobre el Modelo de Contenido de TextBox
5. Datos
5.1. Enlace de Datos
5.1.1. Informacin General sobre el Enlace de Datos
Pag 1 de 473
Pag 2 de 473
Pag 3 de 473
Pag 4 de 473
Pag 5 de 473
4. Controles
Windows Presentation Foundation (WPF) proporciona una completa biblioteca de controles que permiten el
desarrollo de interfaz de usuario (UI), la visualizacin de documentos y la serializacin de entrada manuscrita
digital.
Pag 6 de 473
Pag 7 de 473
comportamiento de Button, es decir, controlar el evento de hacer clic en el botn, pero que desee cambiar el
aspecto del botn ms all de lo que es posible cambiando las propiedades del mismo. En este caso, puede
crear una nueva ControlTemplate.
En el ejemplo siguiente se crea un objeto ControlTemplate para un control Button. ControlTemplate crea Button
con esquinas redondeadas y fondo degradado. ControlTemplate contiene un Border cuyo Background es
LinearGradientBrush con dos objetos GradientStop. El primer GradientStop utiliza el enlace de datos para
enlazar la propiedad Color de GradientStop al color de fondo del botn. Al establecer la propiedad Background
de Button, el color de ese valor se utilizar como primer GradientStop. En el ejemplo tambin se crea un
Trigger que cambia el aspecto de Button cuando IsPressed es true.
<!--Define a template that creates a gradient-colored button.-->
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Border" CornerRadius="20" BorderThickness="1" BorderBrush="Black">
<Border.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="{Binding Background.Color,
RelativeSource={RelativeSource TemplatedParent}}" Offset="0.0" />
<GradientStop Color="White" Offset="0.9" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter Margin="2" HorizontalAlignment="Center"
VerticalAlignment="Center" RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<!--Change the appearance of the button when the user clicks it.-->
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="Border" Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="{Binding Background.Color,
RelativeSource={RelativeSource TemplatedParent}}" Offset="0.0" />
<GradientStop Color="DarkSlateGray" Offset="0.9" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...
<Button Grid.Row="2" Grid.ColumnSpan="2" Name="submitName" Background="Green">
View message</Button>
Nota:
La propiedad Background de Button debe estar establecida en SolidColorBrush para que ejemplo funcione
correctamente.
Suscribirse a eventos
Puede suscribirse a un evento de un control utilizando XAML o cdigo, pero los eventos nicamente se pueden
controlar mediante cdigo. En el ejemplo siguiente se muestra cmo suscribirse al evento Click de un Button.
<Button Grid.Row="2" Grid.ColumnSpan="2" Name="submitName" Click="submit_Click"
Background="Green">View message</Button>
AddHandler submit.Click, AddressOf submit_Click
En el ejemplo siguiente se controla el evento Click de un control Button.
Private Sub submit_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text)
End Sub 'submit_Click
Contenido enriquecido en los controles
Pag 8 de 473
ContentControl: algunos ejemplos de clases que heredan de esta clase son Label, Button y ToolTip.
ItemsControl: algunos ejemplos de clases que heredan de esta clase son ListBox, Menu y StatusBar.
HeaderedContentControl: algunos ejemplos de clases que heredan de esta clase son TabItem,
GroupBox y Expander.
HeaderedItemsControl: algunos ejemplos de clases que heredan de esta clase son MenuItem,
TreeViewItem y ToolBar.
2.
Cree un nuevo proyecto de WPF: En el men Archivo, seale a Nuevo y, a continuacin, haga clic en
Proyecto. Busque la plantilla Aplicacin para Windows (WPF) y asigne al proyecto el nombre
"AnimatedButton". Esto crear el esqueleto para la aplicacin.
3.
Agregue los botones predeterminados bsicos: 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 pgina Lenguaje de marcado de aplicaciones extensible (XAML) escribiendo o copiando
y pegando el siguiente cdigo resaltado en Window1.xaml:
<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">
Pag 9 de 473
4.
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Window>
Presione F5 para ejecutar la aplicacin; debera ver un conjunto de botones parecido a la ilustracin
siguiente.
5.
Ahora que ha creado los botones bsicos, 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 bsicas
A continuacin, establezcamos algunas propiedades de estos botones para controlar su aspecto y su diseo. En
lugar de establecer individualmente las propiedades de los botones, utilizar recursos para definir las
propiedades de botn de toda la aplicacin. Los recursos de aplicacin son conceptualmente similares a Hojas
de estilos en cascada (CSS) externas para pginas web; sin embargo, los recursos son mucho ms eficaces que
Hojas de estilos en cascada (CSS), como ver al final de este tutorial.
2.
recursos
en
Cree un estilo y defina los valores de las propiedades bsicas 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
4.
Pag 10 de 473
5.
Hay mucho ms que puede hacer con estilos, incluidas diversas maneras de ajustar con precisin a
qu objetos se destinan, especificar valores de propiedad complejos e incluso utilizar estilos como entrada
para otros estilos.
6.
Establezca un valor de propiedad de estilo en un recurso: los recursos permiten reutilizar fcilmente
objetos y valores que se definen con frecuencia. Es especialmente til definir valores complejos utilizando
7.
recursos, para hacer el cdigo ms modular. Agregue el marcado resaltado siguiente a app.xaml.
<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
aplicacin como un valor de propiedad, incluso dentro del establecedor de estilo del botn para la
propiedad Background. Ahora, todos los botones tienen un valor de propiedad Background de este
degradado.
8.
Pag 11 de 473
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 dems valores de propiedades que hemos
establecido en un objeto Style, utilizando un objeto Setter. Agregue el marcado resaltado siguiente al
2.
estilo de botn.
<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>
Modifique la presentacin del botn: 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
botn. Un objeto ContentPresenter muestra el contenido del botn. En este tutorial, el contenido es texto
("Button 1", "Button 2", "Button 3"). Todos los componentes de la plantilla (los rectngulos y el control
3.
4.
Agregue un efecto de vidrio a la plantilla: a continuacin 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:
<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" />
Pag 12 de 473
5.
6.
Pag 13 de 473
2.
Pag 14 de 473
3.
4.
5.
clic en l).
<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 aplicacin y haga clic en uno de los botones. Observa que el botn
permanece resaltado despus de hacer clic en l, porque todava tiene el foco. Si hace clic en otro botn,
el nuevo botn obtendr el foco mientras el ltimo lo pierde.
6.
Agregue
animaciones
para
MouseEnter
MouseLeave:
continuacin,
agregamos
algunas
animaciones a los desencadenadores. Agregue el marcado siguiente en cualquier punto del bloque
7.
ControlTemplate.Triggers.
<!-- 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 rectngulo de vidrio se reduce cuando el puntero del mouse pasa sobre el botn y vuelve al tamao
normal cuando el puntero sale.
Pag 15 de 473
Hay dos animaciones que se desencadenan cuando el puntero pasa sobre el botn (cuando se provoca
el evento MouseEnter). Estas animaciones reducen el rectngulo 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 animacin se produce durante medio segundo, y By especifica que el vidrio se reduce un
10%.
9.
10.
Agregue una animacin para cuando se haga clic en el botn: el paso final es agregar un
desencadenador para cuando el usuario haga clic en el botn. Agregue el marcado siguiente en cualquier
Ha personalizado la apariencia de botones de toda la aplicacin 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 animacin.
Pag 16 de 473
de
desencadenadores. La lista siguiente proporciona ejemplos de cmo utilizar estas caractersticas para crear
experiencias personalizadas y coherentes sin tener que crear un nuevo control.
Contenido enriquecido. Muchos de los controles estndar de WPF son compatibles con contenido
enriquecido. Por ejemplo, la propiedad de contenido de un control Button es del tipo Object, de modo
que, en teora, en un control Button se puede mostrar cualquier elemento. Para que un botn muestre
una imagen y texto, puede agregar una imagen y un control TextBlock a StackPanel y asignar
StackPanel a la propiedad Content. Debido a que estos controles permiten mostrar elementos visuales
de WPF y datos arbitrarios, se reduce la necesidad de crear un nuevo control o modificar un control
existente para permitir una visualizacin compleja.
Estilos. Un objeto Style es una coleccin de valores que representan propiedades para un control.
Utilizando estilos, puede crear una representacin reutilizable del aspecto y el comportamiento
deseados para un control sin necesidad de escribir un nuevo control. Por ejemplo, suponga que desea
que la fuente de todos los controles TextBlock sea Arial de color rojo con un tamao de 14. Puede
crear un estilo como un recurso y establecer las propiedades adecuadas en consecuencia. A
continuacin, todos los controles TextBlock que agregue a la aplicacin tendrn la misma apariencia.
Plantillas de datos.DataTemplate permite personalizar cmo se muestran los datos en un control. Por
ejemplo, DataTemplate se puede utilizar para especificar cmo se muestran los datos en ListBox.
Adems de personalizar la apariencia de los datos, un objeto DataTemplate puede incluir elementos de
interfaz de usuario, lo que aporta gran flexibilidad en las interfaces de usuario personalizadas. Por
ejemplo, con DataTemplate se puede crear un control ComboBox en el que cada elemento contenga
una casilla.
Plantillas de control. Muchos controles de WPF utilizan ControlTemplate para definir la estructura y
apariencia del control, a fin de independizar su apariencia de su funcionalidad. Es posible cambiar
drsticamente la apariencia de un control si se redefine su ControlTemplate. Por ejemplo, supongamos
que desea un control semejante a un semforo. La interfaz de usuario y la funcionalidad de este
control son sencillas. El control est compuesto de tres crculos y slo uno de ellos puede estar
encendido en un momento dado. Despus de reflexionar, puede que se d cuenta de que RadioButton
proporciona la funcionalidad de permitir la seleccin de una sola opcin a la vez, aunque la apariencia
predeterminada de RadioButton no se parece nada a un semforo. Dado que RadioButton utiliza una
plantilla de control para definir su apariencia, resulta fcil redefinir ControlTemplate para adaptarlo a
los requisitos del control y utilizar los botones de opcin para crear el semforo.
Nota:
Aunque RadioButton puede utilizar un objeto DataTemplate, en este ejemplo no basta con
DataTemplate. DataTemplate define la apariencia del contenido de un control. En el caso de un botn
de opcin (RadioButton), su contenido es aquello que aparece a la derecha del crculo, que indica si
RadioButton est seleccionado. En el ejemplo del semforo, el botn de opcin tiene que ser slo un
crculo capaz de "encenderse". Dado que el requisito de apariencia del semforo es tan distinto de la
apariencia predeterminada de RadioButton, es necesario redefinir ControlTemplate. En general,
DataTemplate se utiliza para definir el contenido (o los datos) de un control y ControlTemplate se
utiliza para definir la estructura del control.
Pag 17 de 473
Derivar de Control
Derivar de la clase Control es el modelo utilizado por la mayora de los controles WPF existentes. Cuando se
crea un control que hereda de la clase Control, su apariencia se define mediante plantillas. Al hacerlo, se
independiza la lgica de funcionamiento de la representacin visual. Tambin se puede garantizar la
independencia entre la interfaz de usuario y la lgica si se usan comandos y enlaces en lugar de eventos, y se
evita en lo posible hacer referencia a los elementos de ControlTemplate. Si la interfaz de usuario y la lgica del
control estn debidamente desconectadas, un usuario del control podr redefinir el objeto ControlTemplate del
control para personalizar su apariencia. Aunque generar un objeto Control personalizado no es tan sencillo
como generar un objeto UserControl, un objeto Control personalizado proporciona mayor flexibilidad.
Ventajas de derivar de Control
Considere la posibilidad de derivar de Control en lugar de utilizar la clase UserControl si se cumple cualquiera
de las condiciones siguientes:
Desea que la apariencia del control sea personalizable a travs del objeto ControlTemplate.
Desea que el control admita temas diferentes.
Derivar de FrameworkElement
Los controles derivados de UserControl o Control se basan en la composicin de elementos existentes. Para
muchos escenarios, sta es una solucin aceptable, porque cualquier objeto que hereda de FrameworkElement
puede estar en un objeto ControlTemplate. Sin embargo, en ocasiones la apariencia de un control requiere una
Pag 18 de 473
Desea tener un control preciso sobre la apariencia del control ms all de lo que proporciona la simple
composicin de elementos.
Desea definir el aspecto del control definiendo una lgica de representacin propia.
Desea componer elementos existentes de maneras nuevas que excedan lo posible con UserControl y
Control.
utilizar
estas
caractersticas
exactamente
igual
que
para
un
control
distribuido
con
WPF,
Si desea que una propiedad del control admita cualquiera de estas funcionalidades, debe implementarla como
propiedad de dependencia. En el ejemplo siguiente se define una propiedad de dependencia denominada Value
mediante este procedimiento:
Defina
un
identificador
de
DependencyProperty
denominado
ValueProperty
como
campo
El nombre de la propiedad.
El tipo de la propiedad.
El tipo que posee la propiedad.
Los metadatos de la propiedad. Los metadatos contienen el valor predeterminado de la
propiedad, CoerceValueCallback y PropertyChangedCallback.
Defina una propiedad de "contenedor" de CLR denominada Value (que es el mismo nombre que se
utiliza para registrar la propiedad de dependencia) mediante la implementacin de los descriptores de
acceso get y set de la propiedad. Observe que los descriptores de acceso get y set llaman nicamente
a GetValue y SetValue, respectivamente. Se recomienda que los descriptores de acceso de las
propiedades de dependencia no contengan lgica adicional, porque los clientes y WPF pueden omitir
Pag 19 de 473
Los eventos enrutados se pueden utilizar en EventSetter, lo que permite a los programadores de
aplicaciones especificar el controlador de un evento en un estilo.
Los eventos enrutados se pueden utilizar en EventTrigger, lo que resulta til para animar propiedades
mediante XAML.
Pag 20 de 473
Defina
un
identificador
de
RoutedEvent
denominado
ValueChangedEvent
como
campo
Cree un mtodo virtual protegido denominado OnValueChanged que provoque el evento ValueChanged
/// <summary>
/// Identifies the ValueChanged routed event.
/// </summary>
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(
"ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler
<decimal>), typeof(NumericUpDown));
/// <summary>
/// Occurs when the Value property changes.
/// </summary>
public event RoutedPropertyChangedEventHandler<decimal> ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
/// <summary>
/// Raises the ValueChanged event.
/// </summary>
/// <param name="args">Arguments associated with the ValueChanged event.</param>
protected virtual void OnValueChanged(RoutedPropertyChangedEventArgs<decimal> args)
{
RaiseEvent(args);
}
Utilizar el enlace
Para desacoplar la interfaz de usuario del control de su lgica, puede ser conveniente utilizar el enlace de datos.
Esto resulta particularmente importante si la apariencia del control se define mediante ControlTemplate. Al
utilizar el enlace de datos, puede que consiga eliminar la necesidad de hacer referencia a partes concretas de la
interfaz de usuario desde el cdigo. Es conveniente evitar hacer referencia a elementos incluidos en
ControlTemplate, ya que cuando el cdigo hace referencia a elementos incluidos en ControlTemplate y se
modifica ControlTemplate, el elemento al que se hace referencia debe incluirse en el nuevo objeto
ControlTemplate.
En el ejemplo siguiente se actualiza el control TextBlock del control NumericUpDown, para ello se le asigna un
nombre y se hace referencia al cuadro de texto por su nombre en el cdigo.
<Border BorderThickness="1" BorderBrush="Gray" Margin="2"
Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Stretch">
<TextBlock Name="valueText" Width="60" TextAlignment="Right" Padding="5"/>
</Border>
private void UpdateTextBlock()
{
valueText.Text = Value.ToString();
}
En el ejemplo siguiente se utiliza el enlace para lograr lo mismo.
<Border BorderThickness="1" BorderBrush="Gray" Margin="2"
Pag 21 de 473
Pag 22 de 473
Consideremos
una
clase
DependencyProperty
con
el
formato
Implemente
un
par
de
mtodos
publicstatic
CLR
denominados
SetNombreDePropiedad
coincida
con
NombreDePropiedad
el
tipo
debe
de
datos
devolver
registrado
un
valor
para
la
propiedad.
del
mismo
tipo.
El
mtodo
Si
falta
Getmtodo
el
mtodo
Pag 23 de 473
Nivel de elemento: el sistema empieza por el elemento que hace referencia al recurso y, a
continuacin, busca en los recursos del elemento primario lgico, y as sucesivamente, hasta que se
alcanza el elemento raz.
2.
3.
archivos
de
la
carpeta
Temas
corresponden
los
temas.
Por
ejemplo,
puede
tener
Pag 24 de 473
}
En el ejemplo siguiente se combina el recurso compartido con los recursos de un control personalizado en el
constructor
del
control
antes
de
llamar
InitilizeComponent.
Dado
que
Tema de Windows
Classic.xaml
Luna.NormalColor.xaml
Luna.Homestead.xaml
Luna.Metallic.xaml
Royale.NormalColor.xaml
Aero.NormalColor.xaml
No es necesario definir un recurso para cada tema. Si no se ha definido un recurso para un tema concreto, el
control utiliza el recurso genrico, que se encuentra en un archivo de diccionario de recursos llamado
generic.xaml en la misma carpeta que los archivos de diccionario de recursos especficos de un tema. Aunque
generic.xaml no corresponde a un tema concreto de Windows, no deja de ser un diccionario del nivel de tema.
Ejemplo NumericUpDown Custom Control with Theme and UI Automation Support contiene dos diccionarios de
recursos para el control NumericUpDown: uno est en generic.xaml y el otro en Luna.NormalColor.xaml. Puede
ejecutar la aplicacin y cambiar entre el tema plateado de Windows XP y otro tema a fin de ver la diferencia
entre las dos plantillas de control. (Si est ejecutandoWindows Vista, puede cambiar el nombre de
Luna.NormalColor.xaml a Aero.NormalColor.xaml y cambiar entre dos temas, como el de Windows clsico y el
tema predeterminado de Windows Vista.)
Pag 25 de 473
UserControl
with
DependencyProperty
and
RoutedEvent,
NumericUpDown
hereda de
UserControl; en Ejemplo NumericUpDown Custom Control with Theme and UI Automation Support,
NumericUpDown hereda de Control y utiliza un elemento ControlTemplate. En esta seccin se describen
brevemente algunas de las diferencias entre ambos y se explica por qu el control que utiliza ControlTemplate
es ms extensible.
La diferencia ms importante es que el control NumericUpDown que hereda de UserControl no utiliza un
elemento ControlTemplate y el control que hereda directamente de Control s lo utiliza. En el ejemplo siguiente
se muestra XAML del control que hereda de UserControl. Como puede observar, XAML es muy similar al
resultado que podra obtener al crear una aplicacin y comenzar con Window o Page.
<!--XAML for NumericUpDown that inherits from UserControl.-->
<UserControl x:Class="MyUserControl.NumericUpDown"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyUserControl">
<Grid Margin="3">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border BorderThickness="1" BorderBrush="Gray" Margin="2" Grid.RowSpan="2"
VerticalAlignment="Center" HorizontalAlignment="Stretch">
<!--Bind the TextBlock to the Value property-->
<TextBlock
Width="60" TextAlignment="Right" Padding="5"
Text="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type local:NumericUpDown}}, Path=Value}"/>
</Border>
<RepeatButton Name="upButton" Click="upButton_Click"
Grid.Column="1" Grid.Row="0">Up</RepeatButton>
<RepeatButton Name="downButton" Click="downButton_Click"
Pag 26 de 473
Pag 27 de 473
Ejemplo
NumericUpDown
Custom
Control
with
Theme
and
UI
Automation
Support,
el
control
Estilos (incluidos los establecedores de propiedades, los desencadenadores y los guiones grficos).
Recursos.
Plantillas de control.
Plantillas de datos.
Pag 28 de 473
Tenga en cuenta la funcionalidad perifrica de los elementos de la aplicacin auxiliar de la plantilla. Los
controles se deben basar en su funcionalidad bsica y en propuestas reales, y definir mediante el uso
comn del control. Para ello, utilice los elementos de creacin y de la aplicacin auxiliar en la plantilla
para habilitar comportamientos y visualizaciones perifricos; es decir, los comportamientos y
visualizaciones que no contribuyen a la funcionalidad bsica del control. Los elementos de la aplicacin
auxiliar se clasifican en tres categoras:
Los elementos de aplicacin auxiliar basados en tipo son nuevos tipos que encapsulan la
funcionalidad especializada. Estos elementos se suelen disear con un intervalo de funcionalidad
menor que los controles comunes o primitivos. A diferencia de los elementos de la aplicacin
auxiliar independientes, los elementos de aplicacin auxiliar basados en tipo son conscientes del
contexto en el que se usan y, normalmente, deben compartir los datos con el control a cuya
plantilla pertenecen.
Los elementos de aplicacin auxiliar con nombre son los controles comunes o primitivos que
espera un control para buscar por nombre en su plantilla. A estos elementos se les asigna un
nombre conocido en la plantilla para que, de esta forma, el control busque el elemento e
interacte con l mediante programacin. Puede haber slo uno elemento con un nombre concreto
en una plantilla cualquiera.
En la tabla siguiente, se muestran los elementos de aplicacin auxiliar usados por los estilos de control
actuales (esta lista no es una lista completa):
Elemento
Tipo
Utilizado por
ContentPresenter
Basado en
tipo
ItemsPresenter
Basado en
tipo
ToolBarOverflowPanel
Con nombre
ToolBar
Popup
Independiente
RepeatButton
Con nombre
ScrollBar
Con nombre
ScrollViewer
ScrollViewer
Independiente
TabPanel
Independiente
TabControl
TextBox
Con nombre
ComboBox
TickBar
Basado en
tipo
Slider
Reduzca el nmero necesario de enlaces especificados por el usuario o los valores de las propiedades
de los elementos de la aplicacin auxiliar. Es normal que un elemento de aplicacin auxiliar requiera
algunos valores de enlaces o de propiedades para funcionar correctamente en la plantilla del control. El
elemento de la aplicacin auxiliar y el control con plantilla deben establecer estos valores en la medida
Pag 29 de 473
Los elementos de la aplicacin auxiliar con nombre los debe identificar el elemento primario y
ste debe establecer cualquier valor necesario del elemento de la aplicacin auxiliar.
Los elementos de la aplicacin auxiliar basados en tipo deben establecer los valores
necesarios directamente en s mismos. De esta forma, quiz el elemento de la aplicacin auxiliar
deba consultar el contexto de la informacin en la que se usa, incluido su TemplatedParent (el tipo
de control de la plantilla en la que se utiliza). Por ejemplo, ContentPresenter enlaza
automticamente la propiedad Content de su TemplatedParent a su propiedad Content cuando se
usa en un tipo derivado de ContentControl.
Use la propiedad Name para marcar los elementos de una plantilla. Un control que necesite buscar un
elemento en su estilo para tener acceso a l mediante programacin debe hacerlo con la propiedad
Name y el ejemplo de FindName. Un control no debe producir ninguna excepcin cuando no se
encuentre un elemento, sino deshabilitar correctamente la funcionalidad que requera ese elemento.
Utilice los procedimientos recomendados para expresar el estado del control y el comportamiento de
un estilo. A continuacin, se muestra una lista ordenada de los procedimientos recomendados para
expresar los cambios del estado del control y de comportamiento de un estilo. Debe utilizar el primer
elemento de la lista que habilita su escenario.
1. Enlace
de
Propiedad.
Ejemplo:
enlace
entre
ComboBox.IsDropDownOpen
ToggleButton.IsChecked.
2. Cambios de propiedad desencadenados o animaciones de propiedad. Ejemplo: estado de
desplazamiento del puntero de Button.
3. Comando. Ejemplo: LineUpCommand / LineDownCommand de ScrollBar.
4. Elementos independientes de la aplicacin auxiliar. Ejemplo: TabPanel de TabControl.
5. Tipos de aplicacin auxiliar basados en tipo. Ejemplo: ContentPresenter de Button, TickBar de
Slider.
6. Elementos con nombre de la aplicacin auxiliar. Ejemplo: TextBox de ComboBox.
7. Eventos traspasados desde los tipos con nombre de la aplicacin auxiliar. Si realiza escuchas
de eventos traspasados desde un elemento de estilo, es necesario que se pueda identificar
exclusivamente el elemento que genera el evento. Ejemplo: Thumb de ToolBar.
8. Personalice el comportamiento de OnRender. Ejemplo: ButtonChrome de Button.
Sea coherente con los modelos de estilo existentes. Muchas veces existen varias formas de resolver un
problema. Tenga en cuenta y sea coherente con los modelos de los estilos de un control existente en
la medida de lo posible. Esto es especialmente importante para los controles que se derivan del mismo
tipo base (por ejemplo, ContentControl, ItemsControl, RangeBase, etc.).
Pag 30 de 473
Exponga las propiedades para habilitar los escenarios de personalizacin comunes sin volver a crear
plantillas. WPF no admite las partes que se pueden conectar o personalizar; por tanto, al usuario de un
control le quedan slo dos mtodos de personalizacin: establecer las propiedades directamente o
mediante estilos. Teniendo esto presente, es correcto exponer un nmero limitado de propiedades
cuyo destino sean escenarios de personalizacin muy comunes y prioritarios que, de otro modo,
requeriran volver a crear las plantillas. A continuacin se detallan los procedimientos recomendados
para el momento en el que se habilitan los escenarios de personalizacin y cmo se habilitan:
Las personalizaciones muy comunes se deben exponer como propiedades del control y las
debe usar la plantilla.
Es aceptable que las personalizaciones conocidas pero raras requieran que se vuelva a crear
la plantilla.
Los estilos del tema deben intentar ser coherentes con la semntica de la propiedad en todos los
temas, pero sin garantizarlo. Como parte de su documentacin, el control debe tener un documento
que describa la semntica de la propiedad del control; es decir, el "significado" de una propiedad de un
control. Por ejemplo, el control ComboBox debe definir el significado de la propiedad Background
dentro de ComboBox. Los estilos predeterminados del control deben intentar seguir la semntica
definida en ese documento en todos los temas. Los usuarios del control, por otra parte, deben tener en
cuenta que la semntica de la propiedad puede cambiar de un tema a otro. En algunos casos, una
propiedad especificada no se puede expresar en las restricciones visuales requeridas por un tema
concreto. (Por ejemplo, el tema Clsico no tiene ni un solo borde al que se pueda aplicar Thickness
para muchos controles.)
Los estilos del tema no tienen que ser coherentes con la semntica del desencadenador en todos los
temas. El comportamiento expuesto por un estilo de control a travs de los desencadenadores o
animaciones puede variar de un tema a otro. Los usuarios del control deben tener en cuenta que un
control no usar necesariamente el mismo mecanismo para lograr un comportamiento concreto en
todos los temas. Por ejemplo, un tema puede usar una animacin para expresar el comportamiento de
desplazamiento del puntero mientras que otro usa un desencadenador. De esta forma, se pueden
producir incoherencias en la conservacin del comportamiento en los controles personalizados. (Si se
cambia la propiedad de segundo plano, por ejemplo, puede que no afecte el estado de desplazamiento
del puntero del control si dicho estado se expresa con un desencadenador. Sin embargo, si este estado
se implementa utilizando una animacin, al cambiar a segundo plano, se podra interrumpir
irremediablemente la animacin y, por consiguiente, la transicin de estado.)
Los estilos del tema no tiene que ser coherentes con la semntica del "diseo" en todos los temas. Por
ejemplo, el estilo predeterminado no tiene que garantizar que un control vaya a tener el mismo
tamao en todos los temas ni que un control vaya a tener los mismos mrgenes o relleno de contenido
en todos los temas.
4.3.3. Adornos
En esta seccin se proporciona informacin sobre adornos y el marco de trabajo de adornos de Windows
Presentation Foundation (WPF).
Pag 31 de 473
Proporcionar comentarios visuales para indicar diversos estados o en respuesta a distintos eventos.
Superponer etiquetas contextuales visuales en un UIElement.
Invalidar o enmascarar visualmente la totalidad o parte de un UIElement.
Windows Presentation Foundation (WPF) proporciona un marco de trabajo bsico para etiquetar elementos
visuales. En la tabla siguiente se muestra una lista de los tipos principales utilizados al etiquetar objetos y su
finalidad. A continuacin, se presentan varios ejemplos de uso.
Adorner
Una clase base abstracta de la que heredan todas las implementaciones de etiquetas
contextuales concretas.
AdornerLayer
Una clase que representa una capa de representacin para la o las etiquetas
contextuales de uno o ms elementos.
AdornerDecorator
Una clase que permite asociar una capa de etiquetas contextuales a una coleccin de
elementos.
Pag 32 de 473
Llame al mtodo esttico GetAdornerLayer para obtener un objeto AdornerLayer del elemento
UIElement que se va a etiquetar. GetAdornerLayer recorre el rbol visual en sentido ascendente,
empezando por el elemento UIElement especificado, y devuelve la primera capa de etiquetas
contextuales que encuentra. (Si no se encuentra ninguna capa, el mtodo devuelve null.)
2.
Llame al mtodo static GetAdornerLayer para buscar una capa de etiquetas contextuales del elemento
cuyos elementos secundarios desea etiquetar.
2.
Enumere los elementos secundarios del elemento primario y llame al mtodo Add para enlazar una
etiqueta contextual a cada elemento secundario.
Pag 33 de 473
comn
de
implementar
el
comportamiento
de
representacin
es
invalidar
el
mtodo
OnRenderSizeChanged y utilizar uno o ms objetos DrawingContext para representar los elementos visuales del
adorno, segn sea necesario (como se muestra en este ejemplo).
Ejemplo
Un adorno personalizado se crea implementando una clase que hereda de la clase Adorner abstracta. El adorno
del ejemplo simplemente adorna las esquinas de un elemento UIElement con crculos invalidando el mtodo
OnRender.
Public Class SimpleCircleAdorner
Inherits Adorner
Sub New(ByVal adornedElement As UIElement)
MyBase.New(adornedElement)
End Sub
Protected Overrides Sub OnRender(ByVal drawingContext As
System.Windows.Media.DrawingContext)
MyBase.OnRender(drawingContext)
Dim adornedElementRect As New Rect(AdornedElement.DesiredSize)
Dim renderBrush As New SolidColorBrush(Colors.Green)
renderBrush.Opacity = 0.2
Dim renderPen As New Pen(New SolidColorBrush(Colors.Navy), 1.5)
Dim renderRadius As Double
renderRadius = 5.0
'Draw a circle at each corner.
drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopLeft,
renderRadius, renderRadius)
drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopRight,
renderRadius, renderRadius)
drawingContext.DrawEllipse(renderBrush, renderPen,
adornedElementRect.BottomLeft, renderRadius, renderRadius)
drawingContext.DrawEllipse(renderBrush, renderPen,
adornedElementRect.BottomRight, renderRadius, renderRadius)
End Sub
End Class
Llame al mtodo GetAdornerLayer de tipo static para obtener un objeto AdornerLayer del elemento
UIElement que se va a etiquetar. El mtodo GetAdornerLayer recorre el rbol visual en sentido
ascendente, empezando por el elemento UIElement especificado, y devuelve la primera capa de adornos
que encuentra. (Si no se encuentra ninguna capa, el mtodo devuelve null.)
2.
Pag 34 de 473
Declare un nuevo objeto AdornerLayer y llame al mtodo static GetAdornerLayer para encontrar una
capa de adornos para el elemento cuyos elementos secundarios se van a etiquetar.
2.
Enumere los elementos secundarios del elemento primario y llame al mtodo Add para enlazar un
adorno a cada elemento secundario.
ejemplo
de
cdigo
comprimido
es
funcionalmente
equivalente
al
ejemplo
detallado
mostrado
anteriormente. En este cdigo no se comprueba explcitamente si la matriz es null, por lo que es posible que se
inicie una excepcin NullReferenceException. Este cdigo es ms apropiado para aplicaciones en que no sea
frecuente que una matriz sea null.
try { myAdornerLayer.Remove((myAdornerLayer.GetAdorners(myTextBox))[0]); } catch { }
Pag 35 de 473
ejemplo
de
cdigo
comprimido
es
funcionalmente
equivalente
al
ejemplo
detallado
mostrado
anteriormente. En este cdigo no se comprueba explcitamente si la matriz es null, por lo que es posible que se
inicie una excepcin NullReferenceException. Este cdigo es ms apropiado para aplicaciones en que no sea
frecuente que una matriz sea null.
try { foreach (Adorner toRemove in myAdornerLayer.GetAdorners(myTextBox))
myAdornerLayer.Remove(toRemove); } catch { }
Pag 36 de 473
Pag 37 de 473
Pag 38 de 473
Pag 39 de 473
Pag 40 de 473
Pag 41 de 473
Pag 42 de 473
Pag 43 de 473
Pag 44 de 473
Pag 45 de 473
Pag 46 de 473
Pag 47 de 473
Pag 48 de 473
Pag 49 de 473
Pag 50 de 473
Pag 51 de 473
Pag 52 de 473
Pag 53 de 473
Pag 54 de 473
Pag 55 de 473
Pag 56 de 473
Pag 57 de 473
Pag 58 de 473
Pag 59 de 473
Pag 60 de 473
Pag 61 de 473
Pag 62 de 473
Pag 63 de 473
Pag 64 de 473
Pag 65 de 473
Pag 66 de 473
Pag 67 de 473
Pag 68 de 473
Pag 69 de 473
Pag 70 de 473
Pag 71 de 473
Pag 72 de 473
Pag 73 de 473
Pag 74 de 473
Pag 75 de 473
Pag 76 de 473
Pag 77 de 473
Pag 78 de 473
Pag 79 de 473
Pag 80 de 473
Pag 81 de 473
Pag 82 de 473
Pag 83 de 473
Pag 84 de 473
Pag 85 de 473
Pag 86 de 473
Pag 87 de 473
Pag 88 de 473
por
el
nombre
de
la
clase
del
control
terminan
por "AutomationPeer".
Por
ejemplo,
ButtonAutomationPeer es la clase del mismo nivel para la clase del control Button. Las clases del mismo nivel
equivalen, en lneas generales, a los tipos de control de Automatizacin de la interfaz de usuario, pero son
especficas de los elementos de WPF. El cdigo de automatizacin que tiene acceso a las aplicaciones WPF a
travs de la interfaz de Automatizacin de la interfaz de usuario no utiliza los elementos de automatizacin del
mismo nivel directamente, pero el cdigo de automatizacin del mismo espacio de proceso s puede hacerlo.
Clases de automatizacin del mismo nivel integradas
Los elementos implementan una clase de automatizacin del mismo nivel si aceptan actividad de la interfaz por
parte del usuario o si contienen informacin necesaria para los usuarios de aplicaciones de lectores de pantalla.
No todos los elementos visuales de WPF tienen objetos de automatizacin del mismo nivel. Algunos ejemplos
de clases que implementan objetos de automatizacin del mismo nivel son Button, TextBox y Label. Ejemplos
de clases que no implementan objetos de automatizacin del mismo nivel son las clases derivadas de
Decorator, como Border, y las clases basadas en Panel, como Grid y Canvas.
La clase base Control no tiene una clase correspondiente del mismo nivel. Si necesita una clase correspondiente
del mismo nivel para un control personalizado derivado de Control, debe derivar la clase personalizada del
mismo nivel de FrameworkElementAutomationPeer.
Consideraciones de seguridad para elementos del mismo nivel derivados
Los elementos de automatizacin del mismo nivel deben ejecutarse en un entorno de confianza parcial. El
cdigo del ensamblado UIAutomationClient no est configurado para ejecutarse en un entorno de confianza
parcial, por lo que el cdigo de automatizacin de los elementos del mismo nivel no debe hacer referencia a
dicho ensamblado. En su lugar, debera utilizar las clases del ensamblado UIAutomationTypes. Por ejemplo,
debera utilizar la clase AutomationElementIdentifiers del ensamblado UIAutomationTypes, que corresponde a
Pag 89 de 473
ButtonBase,
el
objeto
devuelto
por
OnCreateAutomationPeer
debera
derivarse
de
ButtonBaseAutomationPeer.
Al implementar un control personalizado, debe invalidar los mtodos bsicos ("Core") de la clase base de
automatizacin del mismo nivel que describen el comportamiento nico y especfico del control personalizado.
Invalidar OnCreateAutomationPeer
Invalide el mtodo OnCreateAutomationPeer para el control personalizado, de modo que devuelva el objeto de
proveedor, que debe derivarse directa o indirectamente de AutomationPeer.
Invalidar GetPattern
Aunque los elementos de automatizacin del mismo nivel simplifican algunos aspectos de la implementacin de
proveedores de Automatizacin de la interfaz de usuario de servidor, los elementos de automatizacin del
mismo nivel de controles personalizados an tienen que controlar las interfaces patrn. Al igual que los
proveedores que no son de WPF, los elementos del mismo nivel admiten patrones de controles mediante
implementaciones de interfaces en el espacio de nombres System.Windows.Automation.Provider, como
IInvokeProvider. Las interfaces de patrones de controles las puede implementar el propio elemento del mismo
nivel u otro objeto. La implementacin en el elemento del mismo nivel de GetPattern devuelve el objeto que
admite el patrn especificado. El cdigo de Automatizacin de la interfaz de usuario llama al mtodo
GetPattern y especifica un valor de enumeracin de PatternInterface. El mtodo que invalida GetPattern debera
devolver el objeto que implementa el patrn especificado. Si el control no tiene ninguna implementacin
personalizada de un patrn, puede llamar a la implementacin del tipo base de GetPattern para recuperar su
implementacin o un valor null si no se admite el patrn para este tipo de control. Por ejemplo, un control
NumericUpDown personalizado puede establecerse en un valor dentro de un intervalo, de forma que su
elemento
de
Automatizacin
de
la
interfaz
de
usuario del
mismo
nivel
implemente
la
interfaz
IRangeValueProvider. En el ejemplo siguiente se muestra cmo se invalida el mtodo GetPattern del elemento
del mismo nivel para responder a un valor PatternInterface.RangeValue.
public override object GetPattern(PatternInterface patternInterface)
{
if (patternInterface == PatternInterface.RangeValue)
{
return this;
Pag 90 de 473
Pag 91 de 473
del
mismo
nivel
de
mtodos
bsicos
(core)
mediante
la
inclusin
de
atributos
AutomationProperties. Por ejemplo, el siguiente cdigo XAML crea un botn que tiene dos propiedades
personalizadas de Automatizacin de la interfaz de usuario.
<Button AutomationProperties.Name="Special"
AutomationProperties.HelpText="This is a special button."/>
Implementar proveedores de patrn
Las interfaces implementadas por un proveedor personalizado se declaran explcitamente si el elemento
propietario se deriva directamente de Control. Por ejemplo, en el cdigo siguiente se declara un elemento del
mismo nivel para Control que implementa un valor de intervalo.
public class RangePeer1 : FrameworkElementAutomationPeer, IRangeValueProvider { }
Si el control propietario se deriva de un tipo especfico de control, como RangeBase, el elemento del mismo
nivel puede derivarse de una clase del mismo nivel derivada equivalente. En este caso, el elemento del mismo
nivel
se
derivara
de
RangeBaseAutomationPeer,
que
proporciona
una
implementacin
base
de
IRangeValueProvider. En el cdigo siguiente se muestra la declaracin de este elemento del mismo nivel.
public class RangePeer2 : RangeBaseAutomationPeer { }
Provocar eventos
Los clientes de automatizacin pueden suscribirse a eventos de automatizacin. Los controles personalizados
deben notificar los cambios de estado del control mediante llamadas al mtodo RaiseAutomationEvent. Del
mismo modo, cuando cambie el valor de una propiedad, llame al mtodo RaisePropertyChangedEvent. El cdigo
siguiente muestra cmo obtener el objeto del mismo nivel a partir del cdigo del control y cmo llamar a un
mtodo para provocar un evento. Como medida de optimizacin, el cdigo determina si hay agentes de escucha
para este tipo de evento. Provocar el evento solamente cuando haya agentes de escucha evita una sobrecarga
innecesaria y ayuda a que el control siga respondiendo.
if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged))
{
NumericUpDownAutomationPeer peer =
UIElementAutomationPeer.FromElement(nudCtrl) as NumericUpDownAutomationPeer;
if (peer != null)
{
peer.RaisePropertyChangedEvent(RangeValuePatternIdentifiers.ValueProperty,
(double)oldValue,(double)newValue);
}
}
Border
BulletDecorator
Canvas
DockPanel
Expander
Grid
GridSplitter
Pag 92 de 473
GroupBox
Panel
ResizeGrip
Separator
ScrollBar
ScrollViewer
StackPanel
Thumb
Viewbox
VirtualizingStackPanel
Window
WrapPanel
Botones
El botn es uno de los controles de interfaz de usuario ms bsicos. Las aplicaciones suelen realizar algn tipo
de tarea en el evento Click cuando un usuario hace clic en un botn.
Button
RepeatButton
Mens
Los mens se utilizan para agrupar acciones relacionadas o proporcionar ayuda contextual.
ContextMenu
Menu
ToolBar
Seleccin
Los controles de seleccin se utilizan para permitir al usuario seleccionar una o ms opciones.
CheckBox
ComboBox
ListBox
ListView
TreeView
RadioButton
Slider
Navegacin
Los controles de exploracin mejoran o extienden la experiencia de navegacin en la aplicacin, creando
marcos de destino o el aspecto de una aplicacin con fichas.
Frame
Hyperlink
Page
NavigationWindow
TabControl
Cuadros de dilogo
Los cuadros de dilogo proporcionan compatibilidad concreta para los escenarios de interaccin con el usuario
ms comunes, como la impresin.
OpenFileDialog
PrintDialog
SaveFileDialog
Pag 93 de 473
AccessText
Label
Popup
ProgressBar
StatusBar
TextBlock
ToolTip
Documentos
WPF incluye varios controles especializados para ver documentos. Estos controles optimizan la experiencia de
lectura, basndose en el escenario de destino del usuario.
DocumentViewer
FlowDocumentPageViewer
FlowDocumentReader
FlowDocumentScrollViewer
StickyNoteControl
Entrada
Los controles de entrada permiten al usuario escribir texto y otros contenidos.
TextBox
RichTextBox
PasswordBox
Multimedia
WPF incluye compatibilidad integrada para hospedar contenido de audio y vdeo, as como cdecs para la
mayora de los formatos de imagen ms populares.
Image
MediaElement
SoundPlayerAction
InkCanvas
InkPresenter
Pag 94 de 473
Propiedades de
contenido
Content
Subcategoras
Clases HeaderedContentControl
Clases HeaderedContentControl
Descripcin
Propiedades de contenido
Content, Header
Clases ItemsControl
Descripcin
Propiedades de contenido
Items, ItemsSource
Subcategoras
Clases HeaderedItemsControl
Clases HeaderedItemsControl
Descripcin
Propiedades de contenido
Pag 95 de 473
Clases Decorator
Descripcin
Propiedades de
contenido
Child
Tipo de contenido
principal
Un solo UIElement
Clases Panel
Descripcin
Propiedades de
contenido
Children
Tipo de contenido
principal
Clases Adorner
Descripcin
Propiedades de
contenido
Ninguna.
Tipo de contenido
principal
Ninguno.
Tipo de contenido
principal
Pag 96 de 473
Clase FlowDocument
Clase TextBox
Descripcin
TextBox es un control que se puede utilizar para mostrar o editar texto sin
formato. TextBox nicamente admite texto sin formato. Para aplicaciones que
requieran compatibilidad con contenido ms complejo, consulte RichTextBox.
Propiedades de
contenido
Text
Tipo de contenido
principal
Cadenas
Tipos que
pertenecen a esta
familia de tipos
TextBox
Clase TextBlock
Descripcin
Propiedades de
contenido
Inlines
TextBlock
Clases Shape
Descripcin
Propiedades de
contenido
Ninguna.
Tipo de contenido
principal
Ninguno.
Consulte la clase Shape para obtener una lista de tipos que se derivan de
Shape.
Pag 97 de 473
Estas cuatro clases actan como clases base para la mayora de los controles de WPF. Las clases que usan
estos modelos de contenido pueden contener los mismos tipos de contenido y tratar el contenido de la misma
manera; cualquier tipo de objeto que se puede colocar en ContentControl (o en una clase que hereda de
ContentControl) se puede colocar en un control que tenga cualquiera de los otros tres modelos de contenido. En
la ilustracin siguiente se muestra un control de cada modelo de contenido que contiene una imagen y texto.
ContentControl
El modelo de contenido ms simple de los cuatro es
propiedad Content es del tipo Object, as que no hay ninguna restriccin sobre lo que se puede colocar en
ContentControl. Puede utilizar Lenguaje de marcado de aplicaciones extensible (XAML) o cdigo para establecer
Content.
Los controles siguientes utilizan el modelo de contenido ContentControl:
Button
ButtonBase
CheckBox
ComboBoxItem
ContentControl
Frame
GridViewColumnHeader
GroupItem
Label
ListBoxItem
ListViewItem
NavigationWindow
RadioButton
RepeatButton
ScrollViewer
StatusBarItem
ToggleButton
ToolTip
UserControl
Window
Pag 98 de 473
Una cadena
Un objeto DateTime.
Un UIElement
Un Panel que contiene otros objetos UIElement.
Nota:
En el ejemplo de versin de Lenguaje de marcado de aplicaciones extensible (XAML) se podran utilizar
etiquetas <Button.Content> alrededor del contenido de cada botn, pero no es necesario.
<!--Create a Button with a string as its content.-->
<Button>This is string content of a Button</Button>
<!--Create a Button with a DateTime object as its content.-->
<Button xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
</Button>
<!--Create a Button with a single UIElement as its content.-->
<Button>
<Rectangle Height="40" Width="40" Fill="Blue"/>
</Button>
<!--Create a Button with a panel that contains multiple objects
as its content.-->
<Button>
<StackPanel>
<Ellipse Height="40" Width="40" Fill="Blue"/>
<TextBlock TextAlignment="Center">Button</TextBlock>
</StackPanel>
</Button>
' Add a string to a button.
Dim stringContent As New Button()
stringContent.Content = "This is string content of a Button"
' Add a DateTime object to a button.
Dim objectContent As New Button()
Dim dateTime1 As New DateTime(2004, 3, 4, 13, 6, 55)
objectContent.Content = dateTime1
' Add a single UIElement to a button.
Dim uiElementContent As New Button()
Dim rect1 As New Rectangle()
rect1.Width = 40
rect1.Height = 40
rect1.Fill = Brushes.Blue
uiElementContent.Content = rect1
' Add a panel that contains multpile objects to a button.
Dim panelContent As New Button()
Dim stackPanel1 As New StackPanel()
Dim ellipse1 As New Ellipse()
Dim textBlock1 As New TextBlock()
ellipse1.Width = 40
ellipse1.Height = 40
ellipse1.Fill = Brushes.Blue
textBlock1.TextAlignment = TextAlignment.Center
textBlock1.Text = "Button"
stackPanel1.Children.Add(ellipse1)
stackPanel1.Children.Add(textBlock1)
panelContent.Content = stackPanel1
En la ilustracin siguiente se muestran los cuatro botones creados en el ejemplo anterior.
HeaderedContentControl
HeaderedContentControl hereda la propiedad Content de ContentControl y define la propiedad Header, que es
de tipo Object. Header proporciona un encabezado para el control. Al igual que la propiedad Content de
ContentControl, Header puede ser cualquier tipo. WPF se distribuye con tres controles que heredan de
HeaderedContentControl:
Expander
GroupBox
TabItem
Pag 99 de 473
ItemsControl
Los controles que heredan de ItemsControl contienen una coleccin de objetos. Un ejemplo de ItemsControl es
ListBox. Puede utilizar la propiedad ItemsSource o la propiedad Items para rellenar ItemsControl.
Propiedad ItemsSource
La propiedad ItemsSource de ItemsControl permite utilizar cualquier tipo que implemente IEnumerable como
contenido de ItemsControl. ItemsSource se suele utilizar para mostrar una recoleccin de datos o enlazar un
ItemsControl a un objeto de coleccin.
En el ejemplo siguiente se crea una clase denominada MyData que es una coleccin de cadenas simples.
Public Class MyData
Inherits ObservableCollection(Of String)
Public Sub New() '
Add("Item 1")
Add("Item 2")
Add("Item 3")
End Sub 'New
End Class 'MyData
En el ejemplo siguiente se enlaza ItemsSource a MyData.
<!--Create an instance of MyData as a resource.-->
<src:MyData x:Key="dataList"/>
...
<ListBox ItemsSource="{Binding Source={StaticResource dataList}}"/>
Dim listBox1 As New ListBox()
Dim listData As New MyData()
Dim binding1 As New Binding()
binding1.Source = listData
listBox1.SetBinding(ListBox.ItemsSourceProperty, binding1)
En la ilustracin siguiente se muestra el ListBox creado en el ejemplo anterior.
Propiedad Items
Contenedor de elemento
ComboBox
ComboBoxItem
ContextMenu
MenuItem
ListBox
ListBoxItem
ListView
ListViewItem
Menu
MenuItem
StatusBar
StatusBarItem
TabControl
TabItem
TreeView
TreeViewItem
Puede crear explcitamente un contenedor de elemento para cada elemento de ItemsControl, pero no es
necesario. La creacin o no de un contenedor de elemento en ItemsControl depende en gran medida del
escenario. Por ejemplo, si enlaza datos a la propiedad ItemsSource, no se crea explcitamente un contenedor
de elemento. Es importante tener presentes los puntos siguientes:
Style cuyo TargetType est establecido en un contenedor de elemento se aplica con independencia de
si el contenedor de elemento se crea de manera explcita o no.
Para ilustrar estos puntos, en el ejemplo siguiente se crean dos controles ListBox. En el ejemplo se crean
objetos ListBoxItem para el primer ListBox, pero no para el segundo ListBox. En el segundo caso, ListBoxItem
se crea implcitamente para cada elemento de ListBox.
<!--Explicitly create a ListBoxItem for each item in the ListBox-->
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib"
Name="listBoxItemListBox">
<!-- The <ListBox.Items> element is implicitly used.-->
<ListBoxItem>
This is a string in a ListBox
</ListBoxItem>
<ListBoxItem>
<sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
</ListBoxItem>
<ListBoxItem>
<Rectangle Height="40" Width="40" Fill="Blue"/>
</ListBoxItem>
<ListBoxItem>
<StackPanel>
<Ellipse Height="40" Width="40" Fill="Blue"/>
<TextBlock>Text below an Ellipse</TextBlock>
</StackPanel>
</ListBoxItem>
<!--</ListBox.Items>-->
</ListBox>
...
<!--Create a ListBox that contains a string, a Rectangle,
a Panel, and a DateTime object. These items can be accessed
via the Items property.-->
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib"
Name="simpleListBox">
<!-- The <ListBox.Items> element is implicitly used.-->
This is a string in a ListBox
<sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
<Rectangle Height="40" Width="40" Fill="Blue"/>
<StackPanel Name="itemToSelect">
<Ellipse Height="40" Fill="Blue"/>
<TextBlock>Text below an Ellipse</TextBlock>
</StackPanel>
<TextBlock>String in a TextBlock</TextBlock>
<!--</ListBox.Items>-->
</ListBox>
La herencia de propiedades con los estilos y los contenedores de elementos est relacionada con la estructura
del rbol lgico. Al crear explcitamente el contenedor de elemento, ste forma parte del rbol lgico. Si no se
crea el contenedor de elemento, no forma parte del rbol lgico. En la ilustracin siguiente se muestra la
diferencia en el rbol lgico entre los dos controles ListBox del ejemplo anterior.
Los objetos que heredan de la clase Visual heredan los valores de la propiedad de su elemento primario lgico.
En el ejemplo siguiente se crea un ListBox con dos controles TextBlock y se establece la propiedad Foreground
de ListBox en el color azul. El primer TextBlock, textBlock1, est contenido en un ListBoxItem creado de
manera explcita; el segundo TextBlock, textBlock2, no lo est. En el ejemplo tambin se define Style para un
ListBoxItem que establece el Foreground de ListBoxItem en el color verde.
<!--Create a Style as a Resource.-->
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="Green"/>
</Style>
...
<ListBox Foreground="Blue">
<ListBoxItem>
<TextBlock Name="textBlock1">TextBlock in a ListBoxItem.</TextBlock>
</ListBoxItem>
<TextBlock Name="textBlock2">TextBlock not in a ListBoxItem.</TextBlock>
</ListBox>
En la ilustracin siguiente se muestra el ListBox creado en el ejemplo anterior.
La cadena de textBlock1 es verde y la cadena de textBlock2 es azul, porque cada control TextBlock hereda la
propiedad Foreground de su elemento primario lgico respectivo. El elemento primario lgico de textBox1 es
ListBoxItem, y el elemento primario lgico de textBox2 es ListBox.
HeaderedItemsControl
HeaderedItemsControl hereda de la clase ItemsControl. HeaderedItemsControl define la propiedad Header, que
sigue las mismas reglas que la propiedad Header de un HeaderedContentControl. WPF se distribuye con tres
controles que heredan de HeaderedItemsControl:
MenuItem
ToolBar
TreeViewItem
En el ejemplo siguiente se crea un control TreeViewItem. TreeView contiene un solo TreeViewItem, que tiene la
etiqueta TreeViewItem 1, y contiene los elementos siguientes:
Una cadena.
Un objeto DateTime.
Un TreeViewItem que contiene un Rectangle en su Header.
Un TreeViewItem cuya propiedad Header est establecida en un StackPanel que contiene dos objetos.
Nota:
En el ejemplo se crean de manera explcita objetos TreeViewItem para estos dos ltimos elementos,
porque Rectangle y StackPanel heredan de la clase Visual. El estilo predeterminado de TreeViewItem
establece la propiedad Foreground. Los objetos secundarios heredan el valor de la propiedad del
TreeViewItem creado de manera explcita, lo que suele ser el comportamiento deseado.
Child
En la ilustracin siguiente se muestra un objeto TextBox decorado con un objeto Border a su alrededor.
AdornerDecorator
Border
BulletDecorator
ButtonChrome
ClassicBorderDecorator
InkPresenter
ListBoxChrome
SystemDropShadowChrome
Viewbox
Children
Canvas
DockPanel
Grid
TabPanel
ToolBarOverflowPanel
UniformGrid
StackPanel
ToolBarPanel
VirtualizingPanel
VirtualizingStackPanel
WrapPanel
Inlines
Text
5. Datos
El enlace de datos de Windows Presentation Foundation (WPF) proporciona un mtodo simple y coherente para
que las aplicaciones presenten e interacten con datos. Los elementos se pueden enlazar a los datos desde
gran variedad de orgenes de datos en forma de objetos common language runtime (CLR) y XML. Windows
Presentation Foundation (WPF) tambin proporciona un mecanismo para la transferencia de datos a travs de
las operaciones de arrastrar y colocar.
El ejemplo anterior es la interfaz de usuario de una aplicacin que muestra una lista de artculos subastados. La
aplicacin muestra las caractersticas siguientes de enlace de datos:
El contenido de ListBox se enlaza a una coleccin de objetos AuctionItem. Un objeto AuctionItem tiene
propiedades como Descripcin, StartPrice, StartDate, Categora, SpecialFeatures, etc.
Los datos (objetos AuctionItem ) mostrados en ListBox se incluyen en una plantilla para mostrar la
descripcin y el precio actual de cada artculo. Para ello se utiliza un objeto DataTemplate. Asimismo,
el aspecto de cada artculo depende del valor SpecialFeatures del elemento AuctionItem que se va a
mostrar. Si el valor SpecialFeatures de AuctionItem es Color, el artculo tiene un borde azul. Si el valor
es Highlight, el artculo tiene un borde naranja y una estrella.
El usuario puede agrupar, filtrar u ordenar los datos mediante los controles CheckBox proporcionados.
En la imagen anterior, los controles CheckBox "Group by category" y "Sort by category and date"
estn seleccionados. Es posible que haya observado que los datos se agrupan en funcin de la
categora del producto, y el nombre de las categoras se muestra en orden alfabtico. Aunque no se
aprecia muy bien en la imagen, los artculos estn ordenados tambin por fecha de inicio dentro de
cada categora. Para ello se utiliza una vista de coleccin. En la seccin Enlace a colecciones se
describe este tipo de vistas.
Cuando el usuario selecciona un artculo, ContentControl muestra los detalles del artculo seleccionado.
Esto recibe el nombre de escenario principal-detalle. En la seccin Escenario principal-detalle se
proporciona informacin sobre este tipo de escenario de enlace.
El tipo de la propiedad StartDate es DateTime, que devuelve una fecha que incluye el tiempo en
milisegundos. En esta aplicacin, se ha utilizado un convertidor personalizado para que se muestre una
cadena de fecha ms corta. En la seccin Conversin de datos se proporciona informacin sobre los
convertidores.
Cuando el usuario hace clic en el botn Add Product, se muestra el siguiente formulario:
El usuario puede modificar los campos del formulario, obtener una vista previa de la lista de productos
mediante la vista previa abreviada y los paneles de vista previa ms detallada y, a continuacin, hacer clic en
submit para agregar la nueva lista de productos. Todas las funciones de agrupacin, filtrado y ordenacin
existentes se aplicarn a la nueva entrada. En este caso en concreto, el artculo especificado en la imagen
anterior se mostrar como el segundo artculo dentro de la categora Computer.
Lo que no se muestra en esta imagen es la lgica de validacin proporcionada en el control TextBox Start Date.
Si el usuario escribe una fecha no vlida (con un formato no vlido o una fecha pasada), se le notificar con un
control ToolTip y un signo de exclamacin de color rojo situado junto al control TextBox. En la seccin
Validacin de datos se explica cmo crear lgica de validacin.
Antes de abordar las diferentes caractersticas de enlace de datos citadas anteriormente, en la siguiente seccin
explicaremos los conceptos fundamentales imprescindibles para comprender el enlace de datos de WPF.
Conceptos bsicos del enlace de datos
Independientemente del elemento que se vaya a enlazar y de la naturaleza del origen de datos, cada enlace
sigue siempre el modelo que se muestra en la ilustracin siguiente:
Como se muestra en la ilustracin anterior, el enlace de datos es esencialmente el puente entre el destino del
enlace y el origen del enlace. En la ilustracin se muestran los siguientes conceptos fundamentales del enlace
de datos de WPF:
Normalmente, cada enlace tiene estos cuatro componentes: un objeto de destino del enlace, una
propiedad de destino, un origen del enlace y una ruta de acceso al valor en el origen del enlace que se
va a usar. Por ejemplo, si desea enlazar el contenido de TextBox a la propiedad Nombre de un objeto
Empleado, su objeto de destino es TextBox, la propiedad de destino es la propiedad Text, el valor que
se va a utilizar es Nombre y el objeto de origen es el objeto Empleado.
La propiedad de destino debe ser una propiedad de dependencia. La mayora de las propiedades
UIElement son propiedades de dependencia y la mayora de las propiedades de dependencia, excepto
las de slo lectura, admiten el enlace de datos de forma predeterminada. (Slo los tipos
DependencyObject pueden definir propiedades de dependencia y todos los UIElement se derivan de
DependencyObject).
Si bien no se especifica en la ilustracin, cabe observar que el objeto de origen del enlace no se limita
a un objeto CLR personalizado. El enlace de datos de WPF admite datos en forma de objetos de CLR y
XML. Para proporcionar algunos ejemplos, el origen del enlace puede ser un objeto UIElement,
El enlace OneWay permite que los cambios en la propiedad de origen actualicen automticamente la
propiedad de destino, pero los cambios en la propiedad de destino no se propagan de nuevo a la
propiedad de origen. Este tipo de enlace es adecuado si el control que se va a enlazar es de slo
lectura de forma implcita. Por ejemplo, podra enlazar a un origen como un tablero de cotizaciones o
quizs su propiedad de destino no tenga ninguna interfaz de control para realizar modificaciones, como
un color de fondo enlazado a datos de una tabla. Si no hay necesidad de supervisar los cambios de la
propiedad de destino, con el modo de enlace OneWay evitar el trabajo adicional que supone usar el
modo de enlace TwoWay.
El enlace TwoWay permite que los cambios realizados en la propiedad de origen o en la de destino se
actualicen automticamente en el otro. Este tipo de enlace es adecuado para formularios modificables
u otros escenarios de interfaz de usuario totalmente interactivos. La mayora de las propiedades tienen
el enlace OneWay de forma predeterminada, pero algunas propiedades de dependencia (normalmente
las propiedades de controles modificables por el usuario como la propiedad Text de TextBox y la
propiedad IsChecked de CheckBox) tienen el enlace TwoWay de manera predeterminada. Una manera
de determinar mediante programacin si una propiedad de dependencia se enlaza de forma
predeterminada de modo unidireccional o bidireccional es obtener los metadatos de la propiedad
mediante
GetMetadata
y,
continuacin,
comprobar
el
valor
booleano
de
la
propiedad
BindsTwoWayByDefault.
Si el valor de UpdateSourceTrigger es PropertyChanged, el valor al que apunta la fecha derecha del enlace
TwoWay u OneWayToSource se actualizar en cuanto cambie la propiedad de destino. Sin embargo, si el valor
de UpdateSourceTrigger es LostFocus, ese valor slo se actualizar con el nuevo valor cuando la propiedad de
destino pierda el foco.
Al igual que ocurre con la propiedad Mode, las diferentes propiedades de dependencia tienen valores de
UpdateSourceTrigger predeterminados diferentes. El valor predeterminado de la mayora de las propiedades de
dependencia es PropertyChanged, mientras que la propiedad Text tiene un valor predeterminado de LostFocus.
Esto significa que el origen se suele actualizar cuando la propiedad de destino cambia, lo que es adecuado para
controles CheckBox y otros controles sencillos. Sin embargo, para los campos de texto, la actualizacin cada
vez que se pulsa una tecla puede disminuir el rendimiento y deniega al usuario la oportunidad usual de
retroceder y corregir los errores tipogrficos antes confirmar el nuevo valor. Por ese motivo, la propiedad Text
tiene un valor predeterminado de LostFocus en lugar de PropertyChanged.
En la tabla siguiente se proporciona un escenario de ejemplo para cada valor de UpdateSourceTrigger utilizando
TextBox como ejemplo:
Valor UpdateSourceTrigger
Cundo se actualiza
el valor de origen
LostFocus (valor
predeterminado para
TextBox.Text)
Cuando el control
TextBox pierde el foco
PropertyChanged
Cuando escribe en el
control TextBox
Explicit
Cuando la aplicacin
llama a UpdateSource
Controles
TextBox
en
un
formulario
modificable (slo actualiza los valores de
origen cuando el usuario hace clic en el botn
de envo)
Crear un enlace
Como recapitulacin de algunos de los conceptos descritos en las secciones anteriores, recordemos que un
enlace se establece mediante el objeto Binding y que cada enlace tiene normalmente cuatro componentes: el
destino del enlace, la propiedad de destino, el origen del enlace y una ruta de acceso al valor de origen que se
va a utilizar. En esta seccin se explica cmo configurar un enlace.
Considere el ejemplo siguiente, en el que el objeto de origen del enlace es una clase denominada MyData que
se define en el espacio de nombres SDKSample. En esta demostracin, la clase MyData tiene una propiedad de
cadena denominada ColorName, cuyo valor se establece en "Red". Por tanto, este ejemplo genera un botn con
un fondo rojo.
<DockPanel
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:SDKSample">
<DockPanel.Resources>
<c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<DockPanel.DataContext>
<Binding Source="{StaticResource myDataSource}"/>
</DockPanel.DataContext>
<Button Background="{Binding Path=ColorName}"
Width="150" Height="30">I am bound to be RED!</Button>
</DockPanel>
Si aplicamos este ejemplo a nuestro diagrama bsico, la ilustracin resultante tendr el siguiente aspecto. Se
trata de un enlace OneWay porque la propiedad Background admite el enlace OneWay de forma
predeterminada.
Tal vez se pregunte por qu esto funciona si la propiedad ColorName es de tipo string mientras que la
propiedad Background es de tipo Brush.
Especificar el origen del enlace
Observe que en el ejemplo anterior, el origen del enlace se especifica estableciendo la propiedad DataContext
en el elemento DockPanel. A continuacin, Button hereda el valor DataContext de DockPanel, que es su
elemento primario. Recordemos que el objeto de origen del enlace es uno de los cuatro componentes
necesarios de un enlace. Por tanto, si no se especifica el objeto de origen del enlace, el enlace no funcionar.
Hay varias formas de especificar el objeto de origen del enlace. Utilizar la propiedad DataContext en un
elemento primario es til si va a enlazar varias propiedades al mismo origen. Sin embargo, a veces puede ser
ms adecuado especificar el origen del enlace en declaraciones de enlace individuales. En el ejemplo anterior,
en lugar de utilizar la propiedad DataContext, puede especificar el origen del enlace estableciendo directamente
la propiedad Source en la declaracin de enlace del botn, como en el ejemplo siguiente:
<DockPanel.Resources>
<c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<Button Width="150" Height="30"
Background="{Binding Source={StaticResource myDataSource},
Path=ColorName}">I am bound to be RED!
</Button>
Adems de establecer directamente la propiedad DataContext en un elemento, heredar el valor de DataContext
de un antecesor (como el botn del primer ejemplo) y especificar explcitamente el origen del enlace
estableciendo la propiedad Source en Binding (como el botn del ltimo ejemplo), tambin puede utilizar la
propiedad ElementName o la propiedad RelativeSource para especificar el origen del enlace. La propiedad
objeto
BindingExpression
se
puede
obtener
travs
del
valor
devuelto
por
la
llamada
Pero y si en lugar de una propiedad de tipo string, el objeto de origen del enlace tiene una propiedad Color de
tipo Color? En ese caso, para que el enlace funcione tendr que convertir el valor de la propiedad Color en
algn
valor
que
la
propiedad
Background
acepte.
Tendr
que
crear
un
convertidor
personalizado
Recordemos que las conversiones predeterminadas pueden estar disponibles si el tipo que se va a enlazar
contiene convertidores de tipo. Este comportamiento depender de los convertidores de tipos disponibles en el
destino. Si no est seguro, cree su propio convertidor.
A continuacin, se incluyen algunos escenarios tpicos en los que sera lgico implementar un convertidor de
datos:
Los datos se muestran de forma diferente, dependiendo de la referencia cultural. Por ejemplo, tal vez
desee implementar un convertidor de monedas o un convertidor de fechas y horas del calendario en
funcin de los valores o normas utilizados en una determinada referencia cultural.
Los datos que se utilizan no estn diseados necesariamente para cambiar el valor textual de una
propiedad, sino para cambiar otro valor, como el origen de una imagen, o el color o estilo del texto
que se va a mostrar. En este caso se pueden utilizar convertidores para convertir el enlace de una
propiedad que tal vez no sea adecuada, como el enlace de un campo de texto a la propiedad
Background de una celda de tabla.
Hay varios controles o varias propiedades de controles enlazados a los mismos datos. En ese caso, el
enlace principal podra mostrar simplemente el texto, mientras que los otros enlaces controlan los
aspectos de presentacin, pero se sigue utilizando el mismo enlace como informacin de origen.
Hasta el momento, no hemos proporcionado an una descripcin del enlace MultiBinding, en el que
una propiedad de destino tiene una coleccin de enlaces. En el caso de un enlace MultiBinding, se
utiliza un IMultiValueConverter personalizado para generar un valor final a partir de los valores de los
enlaces. Por ejemplo, el color podra calcularse a partir de los valores de rojo, azul y verde, que
pueden ser valores de los mismos o de diferentes objetos de origen del enlace. Vea la pgina de la
clase MultiBinding para obtener informacin y ejemplos al respecto.
Enlace a colecciones
Un objeto de origen del enlace se puede tratar como un objeto nico cuyas propiedades contienen los datos, o
como una recoleccin de datos de objetos polimrficos que suelen estar agrupados (como el resultado de una
consulta a una base de datos). Hasta ahora slo hemos explicado el enlace a objetos individuales, pero el
enlace a una recoleccin de datos es un escenario comn. Por ejemplo, es habitual utilizar ItemsControl como
ListBox, ListView o TreeView para mostrar una recoleccin de datos.
Afortunadamente, nuestro diagrama bsico an sigue siendo vlido. Si enlaza un ItemsControl a una coleccin,
el diagrama tendr el siguiente aspecto:
Como se muestra en este diagrama, para enlazar ItemsControl a un objeto de coleccin, la propiedad que se
utiliza es ItemsSource. Puede considerar la propiedad ItemsSource como el contenido del ItemsControl.
Observe que el enlace es OneWay porque la propiedad ItemsSource admite el enlace OneWay de forma
predeterminada.
Cmo implementar colecciones
Es posible enumerar cualquier coleccin que implementa la interfaz IEnumerable. Sin embargo, para configurar
enlaces dinmicos de modo que las inserciones o eliminaciones que se realicen en la coleccin actualicen la
interfaz de usuario de forma automtica, la coleccin debe implementar la interfaz INotifyCollectionChanged.
Esta interfaz expone un evento que debe provocarse siempre que se realicen cambios en la coleccin
subyacente.
WPF proporciona la clase ObservableCollection<(Of <(T>)>), que es una implementacin integrada de una
recoleccin de datos que expone la interfaz INotifyCollectionChanged. Observe que para permitir totalmente la
transferencia de valores de datos de los objetos de origen a los destinos, cada objeto de la coleccin que
admite propiedades enlazables debe implementar tambin la interfaz INotifyPropertyChanged. Para obtener un
ejemplo, vea Ejemplo Binding to a Collection. Para obtener ms informacin, vea Informacin general sobre
orgenes de enlaces.
Antes de implementar su propia coleccin, considere la posibilidad de utilizar ObservableCollection<(Of
<(T>)>) o una de las clases de coleccin existentes, como List<(Of <(T>)>), Collection<(Of <(T>)>) y
BindingList<(Of <(T>)>), entre otras muchas. Si cuenta con un escenario avanzado y desea implementar su
propia coleccin, considere la posibilidad de utilizar IList, que proporciona una coleccin no genrica de objetos
a los que se puede obtener acceso individualmente por ndice y, por consiguiente, proporciona el mximo
rendimiento.
Vistas de coleccin
Una vez que ItemsControl est enlazado a una recoleccin de datos, quizs desee ordenar, filtrar o agrupar los
datos. Para ello, se utilizan vistas de coleccin, que son clases que implementan la interfaz ICollectionView.
Qu son las vistas de coleccin?
Notas
IEnumerable
IList
ListCollectionView
Ms rpido.
IBindingList
BindingListCollectionView
Como se muestra en el ejemplo de la seccin anterior, los controles ListBox y ContentControl estn enlazados
al objeto de coleccin completo (o, ms concretamente, a la vista del objeto de coleccin) de AuctionItem. Sin
instrucciones especficas sobre cmo mostrar la recoleccin de datos, el control ListBox muestra una
representacin en forma de cadena de cada objeto de la coleccin subyacente y el control ContentControl
muestra una representacin en forma de cadena del objeto al que est enlazado.
Para resolver ese problema, la aplicacin define objetos DataTemplate. Como se muestra en el ejemplo de la
seccin anterior, ContentControl utiliza explcitamente el objeto detailsProductListingTemplate DataTemplate. El
control ListBox utiliza implcitamente el objeto DataTemplate siguiente al mostrar los objetos AuctionItem en la
coleccin:
<DataTemplate DataType="{x:Type src:AuctionItem}">
<Border BorderThickness="1" BorderBrush="Gray"
Padding="7" Name="border" Margin="3" Width="500">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="86"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Polygon Grid.Row="0" Grid.Column="0" Grid.RowSpan="4"
Fill="Yellow" Stroke="Black" StrokeThickness="1"
StrokeLineJoin="Round" Width="20" Height="20"
Stretch="Fill"
Points="9,2 11,7 17,7 12,10 14,15 9,12 4,15 6,10 1,7 7,7"
Visibility="Hidden" Name="star"/>
<TextBlock Grid.Row="0" Grid.Column="1" Margin="0,0,8,0"
Name="descriptionTitle"
Style="{StaticResource smallTitleStyle}">Description:</TextBlock>
<TextBlock Name="DescriptionDTDataType" Grid.Row="0" Grid.Column="2"
Text="{Binding Path=Description}"
Style="{StaticResource textStyleTextBlock}"/>
<TextBlock Grid.Row="1" Grid.Column="1" Margin="0,0,8,0"
Name="currentPriceTitle"
Style="{StaticResource smallTitleStyle}">Current Price:</TextBlock>
<StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
<TextBlock Text="$" Style="{StaticResource textStyleTextBlock}"/>
<TextBlock Name="CurrentPriceDTDataType"
Text="{Binding Path=CurrentPrice}"
Style="{StaticResource textStyleTextBlock}"/>
</StackPanel>
</Grid>
</Border>
date = DateTime.Parse(value.ToString());
}
catch (FormatException)
{
return new ValidationResult(false, "Value is not a valid date.");
}
if (DateTime.Now.Date > date)
{
return new ValidationResult(false, "Please enter a date in the future.");
}
else
{
return ValidationResult.ValidResult;
}
}
Proceso de validacin
La validacin normalmente se produce cuando el valor de un destino se transfiere a la propiedad de origen del
enlace. Esto se produce en los enlaces TwoWay y OneWayToSource. Como ya se ha comentado, lo que causa
una actualizacin del origen depende del valor de la propiedad UpdateSourceTrigger.
A continuacin, se describe el proceso de validacin: Tenga en cuenta que si se produce un error de validacin
o de cualquier otro tipo en cualquier momento del proceso, ste se detiene.
1.
2.
3.
4.
5.
6.
Si un objeto ValidationRule no pasa en ningn momento por este proceso, el motor de enlace crea un objeto
ValidationError y lo agrega a la coleccin Validation.Errors del elemento enlazado. Antes de que el motor de
enlace ejecute los objetos ValidationRule en un paso determinado, ste quita cualquier objeto ValidationError
que se haya agregado a la propiedad adjunta Validation.Errors del elemento enlazado durante dicho paso. Por
ejemplo, si se produce un error de un objeto ValidationRule cuya propiedad ValidationStep se ha establecido en
UpdatedValue, la prxima vez que se realice el proceso de validacin, el motor de enlace quitar dicho objeto
ValidationError inmediatamente antes de llamar a cualquier objeto ValidationRule que tenga la propiedad
ValidationStep establecida en UpdatedValue.
Descripcin
Objetos common
language runtime
(CLR)
Datos ADO.NET
Datos XML
DependencyObject
Puede enlazar a
DependencyObject.
propiedades
de
dependencia
de
cualquier
objeto
Si desea crear el objeto en XAML, la clase debe tener un constructor predeterminado. En algunos
lenguajes de .NET, como C#, el constructor predeterminado puede crearse automticamente.
Las propiedades que se utilizan como propiedades de origen para un enlace deben ser propiedades
pblicas de la clase. Para los enlaces no se puede tener acceso a las propiedades de interfaz definidas
explcitamente; ni tampoco a las propiedades protegidas, privadas o virtuales que no tengan una
implementacin base.
El tipo de la propiedad declarado en la clase es el tipo que se pasa al enlace. Sin embargo, el tipo que
el enlace utiliza en realidad depende del tipo de la propiedad del destino del enlace, no de la propiedad
de origen. Si existe alguna diferencia de tipos, puede ser conveniente escribir a un convertidor para
administrar la manera de pasar inicialmente la propiedad personalizada al enlace.
Propiedad
CLR
Propiedad
CLR
Propiedad de
dependencia
Dependencia
Propiedad
Nivel de confianza
Plena
confianza
Confianza
parcial
Plena confianza
Confianza
parcial
Clase pblica
Clase privada
No
En esta tabla se describen los puntos importantes siguientes sobre los requisitos de permiso en el enlace de
datos:
Para las propiedades CLR, el enlace de datos funciona siempre que el motor de enlace pueda tener
acceso a la propiedad de origen mediante la reflexin. De lo contrario, el motor de enlace emite una
advertencia que indica que no se puede buscar la propiedad y utiliza el valor de reserva o el valor
predeterminado, si est disponible.
El requisito de permiso para el enlace XML es similar: en un recinto de seguridad de confianza parcial, se
produce un error de XmlDataProvider cuando no se dispone de permiso para tener acceso a los datos de que se
trate.
TaskName (cadena), Description (cadena), Priority (int) y una propiedad de tipo TaskType, que es una Enum con
valores Home y Work.
Lo que ocurre es que, sin ninguna instruccin concreta, el objeto ListBox llama de forma predeterminada a
ToString al intentar mostrar los objetos de la coleccin. Por consiguiente, si el objeto Task reemplaza el mtodo
ToString, el objeto ListBox muestra la representacin de cadena de cada objeto de origen de la coleccin
subyacente.
Por ejemplo, si la clase Task reemplaza el mtodo ToString de esta manera, donde name es el campo para la
propiedad TaskName:
public override string ToString()
{
return name.ToString();
}
Entonces, el objeto ListBox tiene un aspecto similar al siguiente:
Sin embargo, eso resulta limitante e inflexible. Adems, si se est enlazando a datos XML, no podra
reemplazar ToString.
Definir una plantilla de datos simple
La solucin es definir un objeto DataTemplate. Una forma de hacerlo es establecer la propiedad ItemTemplate
del objeto ListBox en un objeto DataTemplate. Lo que especifique en el objeto DataTemplate se convertir en la
estructura visual del objeto de datos. El objeto DataTemplate siguiente es bastante simple. Estamos
proporcionando instrucciones para que cada elemento aparezca como tres elementos TextBlock dentro de un
objeto StackPanel. Cada elemento TextBlock se enlaza a una propiedad de la clase Task.
<ListBox Width="400" Margin="10"
ItemsSource="{Binding Source={StaticResource myTodoList}}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=TaskName}" />
<TextBlock Text="{Binding Path=Description}"/>
<TextBlock Text="{Binding Path=Priority}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
En este ejemplo, el objeto DataTrigger utiliza un objeto Setter para establecer un valor de propiedad. Las clases
de desencadenador tambin tienen propiedades EnterActions y ExitActions, que permiten iniciar un conjunto de
acciones tales como animaciones. Adems, tambin hay una clase MultiDataTrigger que permite aplicar
cambios en funcin de varios valores de propiedad enlazados a datos.
Una manera alternativa de lograr el mismo efecto es enlazar la propiedad BorderBrush a la propiedad TaskType
y utilizar un convertidor de valores para devolver el color en funcin del valor TaskType. La creacin del efecto
anterior mediante un convertidor es ligeramente ms eficaz por lo que se refiere a rendimiento. Adems, la
creacin de un convertidor propio ofrece ms flexibilidad, dado que se proporciona lgica propia. En ltimo
trmino, la tcnica que elija depender del escenario y de sus preferencias.
Cules son los elementos de una plantilla de datos?
En el ejemplo anterior, colocamos el desencadenador dentro del objeto DataTemplate utilizando la propiedad
DataTemplate.Triggers El objeto Setter del desencadenador establece el valor de una propiedad de un elemento
(el elemento Border) que se encuentra dentro del objeto DataTemplate. Sin embargo, si las propiedades que
afectan a Setters no son propiedades de elementos que estn dentro del objeto DataTemplate actual, puede
que sea ms conveniente establecer las propiedades mediante un objeto Style para la clase (si el control que
est enlazando es un control ListBox) ListBoxItem. Por ejemplo, si desea que el objeto Trigger anime el valor
Opacity del elemento cuando el mouse seale a un elemento, defina desencadenadores dentro de un estilo
ListBoxItem.
En general, tenga en cuenta que el objeto DataTemplate se aplica a cada uno de los elementos ListBoxItem
generados (para obtener ms informacin sobre cmo y donde se aplica realmente, vea la pgina
ItemTemplate). El objeto DataTemplate solamente est relacionado con la presentacin y la apariencia de los
objetos de datos. En la mayora de los casos, todos los dems aspectos de la presentacin, tales como el
aspecto que tiene un elemento cuando se selecciona o cmo dispone los elementos el control ListBox, no
pertenecen a la definicin de un objeto DataTemplate.
Elegir una plantilla de datos en funcin de propiedades del objeto de datos
En la seccin La propiedad DataType, explicamos que puede definir diferentes plantillas de datos para
diferentes objetos de datos. Esto es especialmente til cuando se tiene una coleccin CompositeCollection de
diferentes tipos o colecciones con elementos de diferentes tipos. En la seccin Utilizar DataTriggers para aplicar
valores de propiedad hemos mostrado que si se tiene una coleccin del mismo tipo de objetos de datos se
puede crear un objeto DataTemplate y, a continuacin, utilizar desencadenadores para aplicar cambios en
}
return null;
}
}
Podemos declarar entonces TaskListDataTemplateSelector como recurso:
<Window.Resources>
<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
</Window.Resources>
Para utilizar el recurso selector de plantillas, asgnelo a la propiedad ItemTemplateSelector del objeto ListBox.
El objeto ListBox llama al mtodo SelectTemplate de TaskListDataTemplateSelector para cada uno de los
elementos de la coleccin subyacente. La llamada pasa el objeto de datos como parmetro de elemento. El
objeto DataTemplate devuelto por el mtodo se aplica a continuacin a ese objeto de datos.
<ListBox Width="400" Margin="10"
ItemsSource="{Binding Source={StaticResource myTodoList}}"
ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
HorizontalContentAlignment="Stretch"/>
Con el selector de la plantilla en su lugar, el control ListBox aparece ahora como sigue:
Observe que en lugar de utilizar ItemTemplate, puede utilizar ItemTemplateSelector. Consulte la seccin
anterior para ver un ejemplo. De igual forma, en lugar de utilizar ItemContainerStyle, tiene la opcin de utilizar
ItemContainerStyleSelector.
Otras dos propiedades relacionadas con el estilo del control ItemsControl que no se muestran aqu son
GroupStyle y GroupStyleSelector.
Compatibilidad con datos jerrquicos
Hasta ahora solamente hemos examinado cmo enlazar y mostrar una nica coleccin. En ocasiones tendr
colecciones que contengan otras colecciones. La clase HierarchicalDataTemplate se ha diseado para utilizarla
con tipos HeaderedItemsControl para mostrar tales datos. En el ejemplo siguiente, ListLeagueList es una lista
de objetos League. Cada objeto League tiene un Name y una coleccin de objetos Division. Cada Division tiene
un Name y una coleccin de objetos Team, y cada objeto Team tiene un Name.
<Window x:Class="SDKSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="HierarchicalDataTemplate Sample"
xmlns:src="clr-namespace:SDKSample">
<DockPanel>
<DockPanel.Resources>
<src:ListLeagueList x:Key="MyList"/>
<HierarchicalDataTemplate DataType
= "{x:Type src:League}"
ItemsSource = "{Binding Path=Divisions}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType
= "{x:Type src:Division}"
ItemsSource = "{Binding Path=Teams}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type src:Team}">
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</DockPanel.Resources>
<Menu Name="menu1" DockPanel.Dock="Top" Margin="10,10,10,10">
<MenuItem Header="My Soccer Leagues"
ItemsSource="{Binding Source={StaticResource MyList}}" />
</Menu>
<TreeView>
<TreeViewItem ItemsSource="{Binding Source={StaticResource MyList}}"
Header="My Soccer Leagues" />
</TreeView>
</DockPanel>
</Window>
En el caso ms simple, el valor de la propiedad Path es el nombre de la propiedad del objeto de origen
que se usar para el enlace, como Path=PropertyName.
Las subpropiedades de una propiedad se pueden especificar mediante una sintaxis parecida, como en
C#. Por ejemplo, la clusula Path=ShoppingCart.Order establece el enlace a la subpropiedad Order del
objeto o la propiedad ShoppingCart.
Para enlazar a una propiedad asociada, coloque la propiedad asociada entre parntesis. Por ejemplo,
para enlazar a la propiedad asociada DockPanel.Dock, la sintaxis es Path=(DockPanel.Dock).
Los indizadores de una propiedad se pueden especificar entre corchetes despus del nombre de la
propiedad donde se aplica el indizador. Por ejemplo, la clusula Path=ShoppingCart[0] establece el
enlace al ndice que corresponde a cmo se administra la cadena literal "0" en la indizacin interna de
la propiedad. Tambin se admiten indizadores anidados.
Los indizadores y las subpropiedades se pueden mezclar en una clusula Path; por ejemplo,
Path=ShoppingCart.ShippingInfo[MailingAddress,Street].
Dentro de los indizadores puede tener varios parmetros de indizador separados por comas (,). El tipo
de
cada
parmetro
se
puede
especificar
con
parntesis.
Por
ejemplo,
puede
tener
Cuando el origen es una vista de coleccin, el elemento actual puede especificarse con una barra
diagonal (/). Por ejemplo, la clusula Path=/ establece el enlace en el elemento actual de la vista.
Cuando el origen es una coleccin, esta sintaxis especifica el elemento actual de la vista de coleccin
predeterminada.
Se pueden combinar nombres de propiedad y barras diagonales para recorrer las propiedades que son
colecciones. Por ejemplo, Path=/Offices/ManagerName especifica el elemento actual de la coleccin de
origen, que contiene una propiedad Offices que tambin es una coleccin. Su elemento actual es un
objeto que contiene una propiedad ManagerName.
Opcionalmente, se puede usar una ruta de acceso con punto (.) para enlazar al origen actual. Por
ejemplo, Text={Binding} es equivalente a Text={Binding Path=.}.
Mecanismo de escape
Dentro de los indizadores ([ ]), el carcter de intercalacin (^) es el carcter de escape para el
carcter siguiente.
Si establece Path en XAML, tambin deber marcar con caracteres de escape (mediante entidades
XML) algunos caracteres especiales del analizador XML:
Comportamientos predeterminados
El comportamiento predeterminado el siguiente si no se especifica en la declaracin.
Se crea un convertidor predeterminado que intenta hacer una conversin de tipos entre el valor del
origen de enlace y el valor del destino de enlace. Si no se puede realizar una conversin, el convertidor
predeterminado devuelve null.
Siempre que el enlace tenga ya un contexto de datos (por ejemplo, el contexto de datos heredado
procedente de un elemento primario), y que el elemento o la coleccin que ese contexto devuelva sea
adecuado para el enlace sin requerir ninguna modificacin ulterior de la ruta, una declaracin de
enlace puede no tener ninguna clusula: {Binding}. Con frecuencia, los enlaces para estilos de datos
se especifican de este modo, donde el enlace acta en una coleccin.
Propiedad
Descripcin
Source
RelativeSource
Resulta til si desea especificar el origen con relacin a la ubicacin donde se encuentra
el destino de enlace. Algunos escenarios comunes donde puede utilizar esta propiedad
son aqullos en los que desea enlazar una propiedad del elemento a otra propiedad del
mismo elemento o en los que se define un enlace en un estilo o una plantilla.
ElementName
Especifica una cadena que representa el elemento que se desea enlazar. Resulta til si
desear enlazar la propiedad de otro elemento de la aplicacin. Por ejemplo, si desea
utilizar un control Slider para controlar el alto de otro control de la aplicacin, o si desea
enlazar la propiedad Content del control a la propiedad SelectedValue del control
ListBox.
5.1.5.3. Cmo: Hacer que los Datos estn Disponibles para el Enlace en XAML
En este tema se explican maneras diferentes de hacer que los datos estn disponibles para el enlace en
Lenguaje de marcado de aplicaciones extensible (XAML), dependiendo de las necesidades de la aplicacin.
Ejemplo
Si tiene un objeto common language runtime (CLR) al que desea enlazar en XAML, una manera de hacer que
est disponible para el enlace es definirlo como recurso y asignarle una clave x:Key. En el ejemplo siguiente,
tenemos un objeto Person con una propiedad de cadena denominada PersonName. El objeto Person se define
en el espacio de nombres denominado SDKSample.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:SDKSample"
SizeToContent="WidthAndHeight"
Title="Simple Data Binding Sample">
<Window.Resources>
<src:Person x:Key="myDataSource" PersonName="Joe"/>
</Window.Resources>
A continuacin, puede enlazar al objeto en XAML, como se muestra en el ejemplo siguiente.
<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>
Como alternativa, puede utilizar la clase ObjectDataProvider, como en el ejemplo siguiente.
<ObjectDataProvider x:Key="myDataSource" ObjectType="{x:Type src:Person}">
<ObjectDataProvider.ConstructorParameters>
<system:String>Joe</system:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
El enlace se define de la misma manera:
<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>
En este ejemplo concreto, el resultado es el mismo: dispone de TextBlock con el contenido de texto Joe. Sin
embargo, la clase ObjectDataProvider proporciona funcionalidad que permite enlazar al resultado de un
mtodo. Puede optar por utilizar la clase ObjectDataProvider si necesita la funcionalidad que proporciona.
Sin embargo, si el enlace se va a establecer a un objeto que ya se ha creado, deber establecer DataContext
mediante cdigo, como en el ejemplo siguiente.
DataSet myDataSet;
private void OnInit(object sender, EventArgs e)
{
string mdbFile = Path.Combine(AppDataPath, "BookData.mdb");
string connString = string.Format(
"Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}", mdbFile);
OleDbConnection conn = new OleDbConnection(connString);
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM BookTable;", conn);
myDataSet = new DataSet();
adapter.Fill(myDataSet, "BookTable");
// myListBox is a ListBox control.
Si tiene un cuadro de dilogo o un formulario modificable por el usuario y desea diferir las actualizaciones del
origen hasta que el usuario haya terminado de modificar los campos y haga clic en "Aceptar", puede establecer
el valor de UpdateSourceTrigger de los enlaces en Explicit, como en el ejemplo siguiente:
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=Explicit}" />
Cuando se establece el valor de UpdateSourceTrigger en Explicit, el valor del origen cambia nicamente cuando
la aplicacin llama al mtodo UpdateSource. En el siguiente ejemplo se muestra cmo llamar a UpdateSource
para itemNameTextBox.
Me.itemNameTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource()
Me.bidPriceTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource()
// itemNameTextBox is an instance of a TextBox
BindingExpression be =
itemNameTextBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
Nota:
Puede utilizar la misma tcnica para las propiedades de otros controles, pero debe tener presente que el
valor predeterminado de UpdateSourceTrigger de la mayora de las dems propiedades es
PropertyChanged.
Nota:
TwoWay actualiza la propiedad de destino o de origen cada vez que cambia la propiedad de destino o
de origen.
ListBox y ContentControl se enlazan al mismo origen. No se especifican las propiedades Path de ambos
enlaces porque los dos controles se enlazan al objeto de coleccin completo.
2.
Observe que la clase Person invalida el mtodo ToString la manera siguiente. De manera predeterminada,
ListBox llama a ToString y muestra una representacin de cadena de cada objeto en la coleccin enlazada. Por
ello, cada objeto Person aparece como un nombre en ListBox.
Public Overrides Function ToString() As String
Return Me._firstname.ToString
End Function
Nota
La propiedad de destino del vnculo (en este ejemplo, la propiedad Background) debe ser una propiedad
de dependencia.
}
else
{
return new ValidationResult(true, null);
}
}
}
En el ejemplo siguiente se muestra el objeto ControlTemplate validationTemplate personalizado que crea un
signo de admiracin rojo para notificar al usuario la existencia de un error de validacin. Se utilizan plantillas de
control para volver a definir el aspecto de un control.
<ControlTemplate x:Key="validationTemplate">
<DockPanel>
<TextBlock Foreground="Red" FontSize="20">!</TextBlock>
<AdornedElementPlaceholder/>
</DockPanel>
</ControlTemplate>
Como se muestra en el ejemplo siguiente, el objeto ToolTip que muestra el mensaje de error se crea utilizando
el estilo denominado textBoxInError. Si el valor de HasError es true, el desencadenador establece la
informacin sobre herramientas del control TextBox actual en su primer error de validacin. La propiedad
RelativeSource se establece en Self, en referencia al elemento actual.
}
}
return result;
}
}
En el ejemplo siguiente, la propiedad de texto del cuadro de texto enlaza a la propiedad Age del objeto Person,
que est disponible para el enlace mediante una declaracin de recurso a la que se asigna el atributo
x:Keydata. DataErrorValidationRule comprueba los errores de validacin provocados por la implementacin de
IDataErrorInfo.
<TextBox Style="{StaticResource textBoxInError}">
<TextBox.Text>
<!--By setting ValidatesOnExceptions to True, it checks for exceptions
that are thrown during the update of the source property.
An alternative syntax is to add <ExceptionValidationRule/> within
the <Binding.ValidationRules> section.-->
<Binding Path="Age" Source="{StaticResource data}"
ValidatesOnExceptions="True"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<!--DataErrorValidationRule checks for validation
errors raised by the IDataErrorInfo object.-->
<!--Alternatively, you can set ValidationOnDataErrors="True" on the
Binding.-->
<DataErrorValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Como alternativa, en lugar de usar DataErrorValidationRule, puede establecer la propiedad ValidatesOnData
Errors en true.
return resultDateTime;
}
return value;
}
Una vez creado un convertidor, puede agregarlo como recurso en el archivo Lenguaje de marcado de
aplicaciones extensible (XAML). En el ejemplo siguiente, src se asigna al espacio de nombres en el que se
define DateConverter.
<src:DateConverter x:Key="dateConverter"/>
Por ltimo, puede utilizar el convertidor en el enlace mediante la sintaxis siguiente. En el ejemplo siguiente, el
contenido de texto de TextBlock se enlaza a StartDate, que es una propiedad de un origen de datos externo.
<TextBlock Grid.Row="2" Grid.Column="0" Margin="0,0,8,0"
Name="startDateTitle"
Style="{StaticResource smallTitleStyle}">Start Date:</TextBlock>
<TextBlock Name="StartDateDTKey" Grid.Row="2" Grid.Column="1"
Text="{Binding Path=StartDate, Converter={StaticResource dateConverter}}"
Style="{StaticResource textStyleTextBlock}"/>
Los recursos de estilo a los que se hace referencia en el ejemplo anterior se definen en la seccin de recurso del
ejemplo, no mostrada en este tema.
5.1.5.16. Cmo: Navegar por los Objetos de una Coleccin de Datos mediante
CollectionView
Las vistas permiten ver la misma recoleccin de datos de maneras diferentes, segn cmo se ordene, filtre o
agrupe. Las vistas tambin proporcionan el concepto de indicador de registro actual y habilitan el movimiento
del puntero. En este ejemplo se muestra cmo obtener el objeto actual y se navega por los objetos de una
recoleccin de datos utilizando la funcionalidad proporcionada en la clase CollectionView.
Ejemplo
En este ejemplo, myCollectionView es un objeto CollectionView que es una vista de una recoleccin enlazada.
En el ejemplo siguiente, OnButton es un controlador de eventos para los botones Previous y Next de una
aplicacin, que permiten al usuario navegar por la recoleccin de datos. Observe que las propiedades
IsCurrentBeforeFirst y IsCurrentAfterLast informan de si el indicador de registro actual ha alcanzado el principio
o el final de la lista, respectivamente, para que se pueda llamar a MoveCurrentToFirst y MoveCurrentToLast,
segn proceda.
La propiedad CurrentItem de la vista se convierte en Order para devolver el elemento de orden actual de la
recoleccin.
//OnButton is called whenever the Next or Previous buttons
//are clicked to change the currency
private void OnButton(Object sender, RoutedEventArgs args)
{
Button b = sender as Button;
switch (b.Name)
{
case "Previous":
myCollectionView.MoveCurrentToPrevious();
if (myCollectionView.IsCurrentBeforeFirst)
{
myCollectionView.MoveCurrentToLast();
}
break;
case "Next":
myCollectionView.MoveCurrentToNext();
if (myCollectionView.IsCurrentAfterLast)
{
myCollectionView.MoveCurrentToFirst();
}
break;
o = myCollectionView.CurrentItem as Order;
// TODO: do something with the current Order o
}
para
el
evento
Filter.
En
el
ejemplo
siguiente,
listingDataView
es
una
instancia
de
CollectionViewSource.
listingDataView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);
En
el
ejemplo
siguiente
se
muestra
la
implementacin
del
controlador
de
eventos
del
filtro
ShowOnlyBargainsFilter de ejemplo. Este controlador de eventos usa la propiedad Accepted para filtrar objetos
AuctionItem que tienen un CurrentPrice de 25 $ o ms.
private void ShowOnlyBargainsFilter(object sender, FilterEventArgs e)
{
AuctionItem product = e.Item as AuctionItem;
if (product != null)
{
// Filter out products with price 25 or above
if (product.CurrentPrice < 25)
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
}
Los tres controles ListBox estn enlazados al mismo origen. Debe establecer la propiedad Path del
enlace para especificar qu nivel de datos desea que muestre el control ListBox.
2.
5.1.5.21. Cmo: Usar el Patrn Principal Detalle con Datos XML Jerrquicos
En este ejemplo se muestra cmo implementar el patrn principal-detalle con datos XML jerrquicos.
Ejemplo
Este ejemplo es la versin de datos XML del ejemplo descrito en Cmo: Usar el patrn principal-detalle con
datos jerrquicos. En este ejemplo, los datos pertenecen al archivo League.xml. Observe que el tercer control
ListBox realiza el seguimiento de los cambios de seleccin del segundo ListBox enlazndose a su propiedad
SelectedValue.
<Window x:Class="SDKSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Multiple ListBox Binding Sample"
Width="400" Height="200"
Background="Cornsilk">
<Window.Resources>
<XmlDataProvider x:Key="MyList" Source="Data\Leagues.xml"
XPath="Leagues/League"/>
<DataTemplate x:Key="dataTemplate">
<TextBlock Text="{Binding XPath=@name}" />
</DataTemplate>
</Window.Resources>
<DockPanel DataContext="{Binding Source={StaticResource MyList}}">
<StackPanel>
<Label>My Soccer Leagues</Label>
<ListBox ItemsSource="{Binding}"
ItemTemplate="{StaticResource dataTemplate}"
IsSynchronizedWithCurrentItem="true"/>
</StackPanel>
este
ejemplo
se
muestra
cmo
crear
enlazar
una
coleccin
que
se
deriva
de
la
clase
ObservableCollection<(Of <(T>)>), que es una clase de coleccin que proporciona notificaciones cuando se
agregan o quitan elementos.
Ejemplo
En el siguiente ejemplo de cdigo se muestra la implementacin de una coleccin NameList.
Public Class NameList
Inherits ObservableCollection(Of PersonName)
' Methods
Public Sub New()
MyBase.Add(New PersonName("Willa", "Cather"))
MyBase.Add(New PersonName("Isak", "Dinesen"))
MyBase.Add(New PersonName("Victor", "Hugo"))
MyBase.Add(New PersonName("Jules", "Verne"))
End Sub
End Class
Public Class PersonName
' Methods
Public Sub New(ByVal first As String, ByVal last As String)
Me._firstName = first
Me._lastName = last
End Sub
' Properties
En este ejemplo, se muestran los ttulos de los libros porque la propiedad XPath del enlace del objeto TextBlock
en DataTemplate se establece en "Title". Si desea mostrar el valor de un atributo, como el ISBN, deber
establecer ese valor de XPath en "@ISBN".
El mtodo XmlNode.SelectNodes administra las propiedades XPath en WPF. Puede modificar las consultas del
XPath para obtener resultados diferentes. A continuacin se muestran algunos ejemplos para la consulta XPath
en el control ListBox enlazado del ejemplo anterior:
XPath="Book[1]" devolver el primer elemento de libro ("XML in Action"). Observe que los ndices de
XPath se basan en 1, no en 0.
XPath="Book[last()-1]" devolver los elementos de libro del segundo a ltimo libro ("Introducing
Microsoft .NET").
Al ejecutar una consulta XPath, devuelve un objeto XmlNode o una lista de XmlNodes. XmlNode es un objeto
common language runtime (CLR), lo que significa que puede utilizar la propiedad Path para enlazar a las
propiedades de common language runtime (CLR). Estudie de nuevo el ejemplo anterior. Si el resto del ejemplo
permanece igual y cambia el enlace de TextBlock por lo siguiente, ver los nombres de los objetos XmlNodes
devueltos en el control ListBox. En este caso, el nombre de todos los nodos devueltos es "Book".
<TextBlock FontSize="12" Foreground="Red">
<TextBlock.Text>
<Binding Path="Name"/>
</TextBlock.Text>
</TextBlock>
En algunas aplicaciones, puede que no sea oportuno incrustar XML como una isla de datos dentro del cdigo
fuente de la pgina XAML, ya que es imprescindible conocer el contenido exacto de los datos en tiempo de
compilacin. Por consiguiente, tambin se admite la obtencin de los datos de un archivo XML externo, como
en el ejemplo siguiente:
<XmlDataProvider x:Key="BookData" Source="data\bookdata.xml" XPath="Books"/>
Si los datos XML residen en un archivo XML remoto, el acceso a ellos se define asignando una URL adecuada al
atributo Source, como sigue:
5.1.5.27. Cmo: Enlazar a los Resultados de una Consulta LINQ para XML,
XDocument o XElement
En este ejemplo se muestra cmo enlazar datos XML a un elemento ItemsControl mediante XDocument.
Ejemplo
El cdigo XAML siguiente define un elemento ItemsControl e incluye una plantilla de datos para los datos de
tipo Planet en el espacio de nombres XML http://planetsNS. Un tipo de datos XML que ocupa un espacio de
nombres debe incluir el espacio de nombres entre llaves y, si aparece donde podra aparecer una extensin de
marcado XAML, debe preceder al espacio de nombres con una secuencia de escape de llaves. Este cdigo
enlaza a las propiedades dinmicas que corresponden a los mtodos Element y Attribute de la clase XElement.
Las propiedades dinmicas permiten a XAML enlazar a las propiedades dinmicas que comparten los nombres
de los mtodos. Tenga en cuenta cmo la declaracin de espacio de nombres predeterminada para XML no se
aplica a los nombres de atributo.
<StackPanel Name="stacky">
<StackPanel.Resources>
<DataTemplate DataType="{}{http://planetsNS}Planet" >
<StackPanel Orientation="Horizontal">
<TextBlock Width="100" Text="{Binding
Path=Element[{http://planetsNS}DiameterKM].Value}" />
<TextBlock Width="100" Text="{Binding Path=Attribute[Name].Value}" />
<TextBlock Text="{Binding Path=Element[{http://planetsNS}Details].Value}" />
</StackPanel>
</DataTemplate>
</StackPanel.Resources>
<ItemsControl
ItemsSource="{Binding }" >
</ItemsControl>
</StackPanel>
El cdigo de C# siguiente llama a Load y establece el contexto de datos del panel de pila en todos los
subelementos del elemento denominado SolarSystemPlanets en el espacio de nombres XML http://planetsNS.
planetsDoc = XDocument.Load("../../Planets.xml");
stacky.DataContext =
planetsDoc.Element("{http://planetsNS}SolarSystemPlanets").Elements();
Los datos XML pueden almacenarse como recurso XAML mediante ObjectDataProvider. Para obtener un ejemplo
completo, vea Cdigo de origen de L2DBForm.xaml. En el ejemplo siguiente se muestra cmo el cdigo puede
establecer el contexto de datos en un recurso de objetos.
planetsDoc = (XDocument)((ObjectDataProvider)Resources["justTwoPlanets"]).Data;
stacky.DataContext =
planetsDoc.Element("{http://planetsNS}SolarSystemPlanets").Elements();
Las propiedades dinmicas que se asignan a Element y Attribute proporcionan flexibilidad dentro de XAML. Su
cdigo tambin puede enlazar a los resultados de una consulta LINQ for XML. Este ejemplo enlaza a los
resultados de la consulta ordenados por un valor de elemento.
stacky.DataContext =
from c in planetsDoc.Element("{http://planetsNS}SolarSystemPlanets").Elements()
orderby Int32.Parse(c.Element("{http://planetsNS}DiameterKM").Value)
select c;
2.
3.
Luego, llame al mtodo del servicio web y establezca la propiedad DataContext del control o la ventana de que
se trate en el objeto devuelto. El mtodo GetContent del servicio MTPS toma una referencia al objeto
getContentRequest. Por consiguiente, en el ejemplo siguiente se configura primero un objeto de solicitud:
// 1. Include the web service namespace
using BindtoContentService.com.microsoft.msdn.services;
// 2. Set up the request object
// To use the MSTP web service, we need to configure and send a request
// In this example, we create a simple request that has the ID of the XmlReader.Read
method page
getContentRequest request = new getContentRequest();
request.contentIdentifier = "abhtw0f1";
// 3. Create the proxy
ContentService proxy = new ContentService();
// 4. Call the web service method and set the DataContext of the Window
// (GetContent returns an object of type getContentResponse)
This.DataContext = proxy.GetContent(request);
Una vez establecido DataContext, puede crear enlaces a las propiedades del objeto en que se ha establecido
DataContext. En este ejemplo, DataContext se ha establecido en el objeto getContentResponse devuelto por
el mtodo GetContent. En el ejemplo siguiente, ItemsControl muestra los valores de locale de
availableVersionsAndLocales de getContentResponse, y se enlaza a esta propiedad.
<ItemsControl Grid.Column="1" Grid.Row="2" Margin="0,3,0,0"
ItemsSource="{Binding Path=availableVersionsAndLocales}"
DisplayMemberPath="locale"/>
Los datos en s pueden estar compuestos de cualquier elemento que se puede representar como una clase base
Object. El formato de datos correspondiente es una cadena o Type que proporciona informacin sobre el
formato de los datos. Los objetos de datos permiten hospedar varios pares de datos-(formato de datos); esto
permite que un mismo objeto de datos proporcione los datos en varios formatos.
Todos los objetos de datos deben implementar la interfaz IDataObject, que proporciona el siguiente conjunto de
mtodos estndar que habilitan y facilitan la transferencia de datos.
Mtodo
Resumen
GetData
GetDataPresent
GetFormats
Devuelve una lista de formatos en los que se almacenan los datos de este objeto de
datos; o bien, a los que se pueden convertir.
SetData
WPF proporciona una implementacin bsica de IDataObject en la clase DataObject; la clase DataObject
estndar es suficiente para numerosos escenarios de transferencia de datos.
Resumen
GiveFeedback
QueryContinueDrag
Este evento se produce cuando hay un cambio en el estado del teclado o del
botn del mouse durante una operacin de arrastrar y colocar, y permite al
origen de colocacin cancelar la operacin de arrastrar y colocar en funcin
de ese estado. Se trata de un evento de propagacin.
PreviewGiveFeedback
PreviewQueryContinueDrag
Resumen
DragEnter
Este evento se produce cuando se arrastra un objeto a los lmites del destino de
colocacin. Se trata de un evento de propagacin.
DragLeave
Este evento se produce cuando se arrastra un objeto fuera de los lmites del destino
de colocacin. Se trata de un evento de propagacin.
DragOver
Este evento se produce cuando se arrastra (mueve) un objeto dentro de los lmites
del destino de colocacin. Se trata de un evento de propagacin.
Drop
PreviewDragEnter
PreviewDragLeave
PreviewDragOver
PreviewDrop
// Take some action if/when data in the string data format is found.
break;
Cree un nuevo objeto de datos que nicamente contendr los datos que desea conservar.
"Copie" los datos deseados de del objeto de datos anterior al nuevo. Para copiar los datos, utilice uno
de los mtodos GetData para recuperar una clase Object que contiene los datos sin procesar y, a
continuacin, utilice uno de los mtodos SetData para agregar los datos al nuevo objeto de datos.
3.
Los mtodos SetData nicamente agregan datos a un objeto de datos; no reemplazan esos datos, aunque
los datos y el formato de datos sean exactamente iguales que en una llamada anterior. Al llamar dos veces
a SetData para obtener los mismos datos con idntico formato de datos har que el par de datos y formato
de datos est presente dos veces en el objeto de datos.
6. Documentos
Windows Presentation Foundation (WPF) proporciona un conjunto verstil de componentes que permiten a los
programadores generar aplicaciones con caractersticas de documento avanzadas y una experiencia de lectura
mejorada. Adems de las mejoras en las funciones y en la calidad, Windows Presentation Foundation (WPF)
proporciona servicios de administracin simplificados para el empaquetado, la seguridad y el almacenamiento
de los documentos.
la
presentacin
de
contenido
de
documentos
dinmicos:
FlowDocumentReader,
dinmicamente
entre
distintos
modos
de
visualizacin,
FlowDocumentPageViewer
FlowDocumentScrollViewer proporcionan visores de contenido dinmico ms ligeros que son fijos para un modo
de visualizacin concreto.
FlowDocumentPageViewer y FlowDocumentScrollViewer
FlowDocumentPageViewer muestra el contenido en el modo de visualizacin de una sola pgina, mientras que
FlowDocumentScrollViewer
muestra
el
contenido
en
modo
del
desplazamiento
continuo.
Tanto
Basndose en las API de empaquetado, XpsDocument est diseado especficamente para almacenar
documentos de contenido fijo de WPF. XpsDocument es un documento autnomo que se puede abrir en un
visor, mostrar en un control DocumentViewer, enrutar a una cola de impresin o imprimir directamente en una
impresora compatible con XPS.
Empaquetar componentes
Las API de empaquetado de WPF permiten organizar los datos y documentos de la aplicacin en una sola
unidad porttil. Un archivo ZIP es uno de los tipos ms comunes de paquetes y constituye el tipo de
empaquetado predeterminado proporcionado con WPF. Package es una clase abstracta desde la que se
implementa ZipPackage mediante una arquitectura de archivos XML de norma abierta y ZIP. De manera
predeterminada, el mtodo Open utiliza ZipPackage para crear y utilizar los archivos ZIP. Un paquete puede
contener tres tipos bsicos de elementos:
PackagePart
PackageDigitalSignature
PackageRelationship
PackageParts
Una clase PackagePart ("elemento") es una clase abstracta que hace referencia a un objeto que est
almacenado en una clase Package. En un archivo ZIP, los elementos del paquete corresponden a los archivos
individuales
almacenados
dentro
del
archivo
ZIP.
ZipPackagePart
proporciona
la
implementacin
predeterminada para los objetos serializables almacenados en ZipPackage. Como en un sistema de archivos, los
elementos contenidos en el paquete se almacenan con una organizacin de directorios jerrquicos o "de
carpetas". Gracias a las API de empaquetado de WPF, las aplicaciones pueden escribir, almacenar y leer varios
objetos PackagePart utilizando un solo contenedor de archivos ZIP.
PackageDigitalSignatures
Para aportar seguridad, es posible asociar PackageDigitalSignature ("firma digital") a los elementos de un
paquete. PackageDigitalSignature incorpora un 509 que proporciona dos caractersticas:
1.
2.
El elemento puede estar firmada digitalmente o cifrada, lo que evitara cualquier modificacin.
Las relaciones de los paquetes proporcionan un medio reconocible de agregar y asociar informacin adicional a
los elementos individuales o al paquete completo. Las relaciones de los paquetes se utilizan para dos funciones
primarias:
1.
2.
Definir las relaciones de informacin que agregan notas u otros datos relacionadas con el elemento.
las
API.NET
Framework
System.Windows.Documents.Serialization
proporcionan
otras
caractersticas importantes.
Caractersticas de los serializadores de documentos de .NET Framework 3.0
El acceso directo a los objetos de documento de alto nivel (rbol lgico y visual) permite el
almacenamiento eficaz de contenido paginado, elementos 2D y 3D, imgenes, multimedia,
hipervnculos, anotaciones y otro contenido de compatibilidad.
Acceso en todo el sistema para su uso por parte de todas las aplicaciones .NET Framework.
Sencilla capacidad de detectar complementos de aplicaciones.
Implementacin, instalacin y actualizacin sencillas de complementos personalizados de
otros fabricantes.
API
System.Windows.Documents.Serialization
proporcionan
compatibilidad
con
serializadores
de
complemento y serializadores vinculados que se instalan por separado con respecto a la aplicacin, se enlazan
en tiempo de ejecucin y permiten el acceso mediante el mecanismo de deteccin SerializerProvider. Los
serializadores de complemento proporcionan ventajas mejoradas de facilidad de implementacin y uso en todo
el sistema. Los serializadores vinculados tambin se pueden implementar para los entornos de confianza parcial
tales como Aplicaciones del explorador XAML (XBAPs), donde no es posible tener acceso a los serializadores de
complemento. Los serializadores vinculados, que se basan en una implementacin derivada de la clase
SerializerWriter, se compilan y vinculan directamente en la aplicacin. Tanto los serializadores de complemento
como los vinculados funcionan a travs de mtodos y eventos pblicos idnticos, lo que facilita el uso de uno o
ambos tipos de serializadores en la misma aplicacin.
Los serializadores de complemento ayudan a los programadores de aplicaciones proporcionando extensibilidad
a los nuevos diseos de almacenamiento y formatos de archivo sin tener que codificar directamente cada
formato potencial en tiempo de compilacin. Los serializadores de complemento tambin benefician a los
programadores de otros fabricantes, al constituir un medio normalizado para implementar, instalar y actualizar
complementos accesibles por el sistema para los formatos de archivo personalizados o de propietario.
Utilizar un serializador de complemento
Los serializadores de complemento son de uso sencillo. La clase SerializerProvider enumera un objeto
SerializerDescriptor para cada complemento instalado en el sistema. La propiedad IsLoadable filtra los
complementos instalados segn la configuracin actual y comprueba que la aplicacin pueda cargar y utilizar el
serializador.
SerializerDescriptor
tambin
proporciona
otras
propiedades,
tales
como
DisplayName
DefaultFileExtension, que la aplicacin puede utilizar para solicitar al usuario la seleccin de un serializador para
un formato de salida disponible. Se proporciona un serializador de complemento predeterminado para XPS con
.NET Framework, que siempre se enumera. Despus de que el usuario selecciona un formato de salida, se
utiliza el mtodo CreateSerializerWriter para crear una clase SerializerWriter para el formato concreto. A
continuacin, se puede llamar al mtodo SerializerWriter.Write para generar la secuencia de salida del
documento al almacn de datos.
En el ejemplo siguiente se muestra una aplicacin que utiliza el mtodo SerializerProvider en una propiedad
PlugInFileFilter. PlugInFileFilter enumera los complementos instalados y genera una cadena de filtro con las
opciones de archivo disponibles para SaveFileDialog.
// ------------------------ PlugInFileFilter -------------------------/// <summary>
///
Gets a filter string for installed plug-in serializers.</summary>
/// <remark>
///
PlugInFileFilter is used to set the SaveFileDialog or
///
OpenFileDialog "Filter" property when saving or opening files
///
using plug-in serializers.</remark>
private string PlugInFileFilter
{
get
{
// Create a SerializerProvider for accessing plug-in serializers.
SerializerProvider serializerProvider = new SerializerProvider();
string filter = "";
// For each loadable serializer, add its display
// name and extension to the filter string.
foreach (SerializerDescriptor serializerDescriptor in
serializerProvider.InstalledSerializers)
{
if (serializerDescriptor.IsLoadable)
{
// After the first, separate entries with a "|".
if (filter.Length > 0)
filter += "|";
// Add an entry with the plug-in name and extension.
filter += serializerDescriptor.DisplayName + " (*" +
serializerDescriptor.DefaultFileExtension + ")|*" +
serializerDescriptor.DefaultFileExtension;
}
}
// Return the filter string of installed plug-in serializers.
return filter;
}
Implementar y depurar el serializador en primer lugar como serializador vinculado. Crear inicialmente
el serializador compilado y vinculado directamente en una aplicacin de prueba proporciona acceso
total a los puntos de interrupcin y a otros servicios de depuracin tiles para la realizacin de
pruebas.
2.
Una vez probado completamente el serializador, se agrega una interfaz ISerializerFactory para crear
un complemento. La interfaz ISerializerFactory permite el acceso pleno a todos los objetos .NET
Framework, lo que incluye el rbol lgico, los objetos UIElement, IDocumentPaginatorSource y los
elementos Visual. Por aadidura, ISerializerFactory proporciona los mismos mtodos y eventos
sincrnicos y asincrnicos utilizados por los serializadores vinculados. Puesto que los documentos
grandes pueden tardar tiempo en generarse, se recomiendan operaciones asincrnicas para mantener
la sensibilidad a las interacciones con el usuario y proporcionar una opcin de cancelacin si se
presenta cualquier problema con el almacn de datos.
3.
Una vez creado el serializador de complemento, se implementa un script de instalacin para distribuir
e instalar (y desinstalar) el complemento.
6.3. Anotaciones
de
documentos
de
WPF
que
admiten
anotaciones
incluyen
FlowDocumentReader
En el ejemplo siguiente se muestra el mtodo que puede utilizar para habilitar la compatibilidad con las
anotaciones en la aplicacin.
// ------------------------ StartAnnotations -------------------------/// <summary>
///
Enables annotations and displays all that are viewable.</summary>
private void StartAnnotations()
{
// If there is no AnnotationService yet, create one.
if (_annotService == null)
// docViewer is a document viewing control named in Window1.xaml.
_annotService = new AnnotationService(docViewer);
// If the AnnotationService is currently enabled, disable it.
if (_annotService.IsEnabled == true)
_annotService.Disable();
// Open a stream to the file for storing annotations.
_annotStream = new FileStream(_annotStorePath, FileMode.OpenOrCreate,
FileAccess.ReadWrite);
// Create an AnnotationStore using the file stream.
_annotStore = new XmlStreamStore(_annotStream);
// Enable the AnnotationService using the new store.
_annotService.Enable(_annotStore);
}// end:StartAnnotations()
Resaltados
Para crear una anotacin, el usuario suele seleccionar primero algn texto o elemento de inters y, a
continuacin, hacer clic con el botn secundario del mouse para mostrar un ContextMenu de opciones de
anotacin. En el ejemplo siguiente se muestra Lenguaje de marcado de aplicaciones extensible (XAML) que
puede utilizar para declarar ContextMenu con comandos enrutados a los que el usuario puede tener acceso para
crear y administrar anotaciones.
<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 & Notes" />
</ContextMenu>
</DocumentViewer.ContextMenu>
Delimitacin de datos
Annotations Framework enlaza las anotaciones a los datos que el usuario selecciona, no slo a una posicin en
la vista de presentacin. Por consiguiente, si la vista del documento cambia, como cuando el usuario se
desplaza o cambia el tamao de la ventana de presentacin, la anotacin permanece con la seleccin de datos
a la que est enlazada. Por ejemplo, en el grfico siguiente se muestra una anotacin que el usuario ha
realizado en una seleccin de texto. Cuando la vista del documento cambia (se desplaza, cambia de tamao,
cambia de escala o se mueve de cualquier otro modo), la anotacin de resaltado se mueve a la par que la
seleccin de datos original.
}
Otro ejemplo de escenario es el de las aplicaciones que habilitan el intercambio de anotaciones y notas rpidas
entre los lectores del documento a travs del correo electrnico. Esta caracterstica permite que estas
aplicaciones naveguen por el lector hasta la pgina que contiene la anotacin intercambiada.
El esquema principal define la estructura XML primaria de un objeto Annotation. La mayora de los elementos
XML
definidos
en
el
esquema
principal
corresponden
los
tipos
del
espacio
de
nombres
System.Windows.Annotations. El esquema principal expone tres puntos de extensin donde las aplicaciones
pueden agregar sus propios datos XML. Estos puntos de extensin incluyen Authors, ContentLocatorPart y los
elementos de contenido. (Los elementos de contenido se proporcionan en forma de una lista XmlElement.)
El esquema base descrito en este tema define las extensiones para Authors, ContentLocatorPart y los tipos de
contenido incluidos con la versin de Windows Presentation Foundation (WPF) inicial.
Esquema principal de anotaciones XML
El esquema principal de anotaciones XML define la estructura XML que se utiliza para almacenar objetos
Annotation.
<xsd:schema elementFormDefault="qualified" attributeFormDefault="unqualified"
blockDefault="#all" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.microsoft.com/windows/annotations/2003/11/core"
xmlns:anc="http://schemas.microsoft.com/windows/annotations/2003/11/core">
<!-- The Annotations element groups a number of annotations. -->
<xsd:element name="Annotations" type="anc:AnnotationsType" />
<xsd:complexType name="AnnotationsType">
<xsd:sequence>
<xsd:element name="Annotation" minOccurs="0" maxOccurs="unbounded"
type="anc:AnnotationType" />
</xsd:sequence>
</xsd:complexType>
<!-- AnnotationType defines the structure of the Annotation element. -->
<xsd:complexType name="AnnotationType">
<xsd:sequence>
<!-- List of 0 or more authors. -->
<xsd:element name="Authors" minOccurs="0" maxOccurs="1"
type="anc:AuthorListType" />
<!-- List of 0 or more anchors. -->
<xsd:element name="Anchors" minOccurs="0" maxOccurs="1"
type="anc:ResourceListType" />
<!-- List of 0 or more cargos. -->
<xsd:element name="Cargos" minOccurs="0" maxOccurs="1"
type="anc:ResourceListType" />
</xsd:sequence>
De momento, aqu tiene un ejemplo de cdigo simple que crea un documento dinmico compuesto por un
prrafo con texto en negrita y una lista.
<!-- This simple flow document includes a paragraph with some
bold text in it and a list. -->
<FlowDocumentReader xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<FlowDocument>
<Paragraph>
<Bold>Some bold text in the paragraph.</Bold>
Some text that is not bold.
</Paragraph>
<List>
<ListItem>
<Paragraph>ListItem 1</Paragraph>
</ListItem>
<ListItem>
<Paragraph>ListItem 2</Paragraph>
</ListItem>
<ListItem>
<Paragraph>ListItem 3</Paragraph>
</ListItem>
</List>
</FlowDocument>
</FlowDocumentReader>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace SDKSample
{
public partial class SimpleFlowExample : Page
{
public SimpleFlowExample()
{
Paragraph myParagraph = new Paragraph();
// Add some Bold text to the paragraph
myParagraph.Inlines.Add(new Bold(new Run("Some bold text in the paragraph.")));
// Add some plain text to the paragraph
myParagraph.Inlines.Add(new Run(" Some text that is not bold."));
// Create a List and populate with three list items.
}
La ilustracin siguiente muestra la apariencia de este fragmento de cdigo.
En este ejemplo, el control FlowDocumentReader se utiliza para hospedar el contenido dinmico. Los elementos
Paragraph, List, ListItem y Bold se utilizan para controlar el formato del contenido, basndose en su orden en el
marcado. Por ejemplo, el elemento Bold abarca slo una parte del texto del prrafo; como resultado, slo ese
fragmento de texto est en negrita. Si ha utilizado HTML, esto le resultar familiar.
Tal y como se muestra en la ilustracin anterior, los documentos dinmicos tienen varias caractersticas
integradas:
Controles de navegacin de pginas: si el modo de visualizacin del documento utiliza pginas, los
controles de navegacin de pginas incluyen un botn que permite saltar a la pgina siguiente (flecha
abajo) o a la pgina anterior (flecha arriba), as como indicadores del nmero de pgina actual y el
nmero total de pginas. Tambin es posible pasar las pginas utilizando las teclas de direccin del
teclado.
Zoom: los controles de zoom permiten al usuario aumentar o reducir el nivel de zoom haciendo clic en
los botones con el signo ms y el signo menos, respectivamente. Los controles de zoom incluyen
tambin un control deslizante para ajustar el nivel de zoom.
Estas caractersticas se pueden modificar dependiendo del control utilizado para hospedar el contenido
dinmico. En la seccin siguiente se describen los distintos controles.
Tipos de documentos dinmicos
La presentacin y la apariencia del contenido en los documentos dinmicos dependern del objeto utilizado para
hospedar el contenido dinmico. Hay cuatro controles que permiten la visualizacin del contenido dinmico:
FlowDocumentReader, FlowDocumentPageViewer, RichTextBox y FlowDocumentScrollViewer. Estos controles se
describen brevemente a continuacin.
muestra
el
contenido
en
modo
de
desplazamiento
continuo.
Tanto
Clases relacionadas con el flujo: cada una de las clases utilizadas en el contenido dinmico tiene un
propsito concreto. Adems, la relacin jerrquica entre las clases dinmicas le ayuda a entender
cmo se utilizan. Por ejemplo, las clases derivadas de la clase Block se utilizan para contener otros
objetos, mientras que las clases derivadas de Inline contienen objetos que se muestran.
2.
Clases derivadas inline: tambin denominadas "elementos de contenido inline " o simplemente
"elementos inline". Los elementos que heredan de Inline estn incluidos dentro de un elemento de
bloque o de otro elemento inline. Los elementos inline se utilizan a menudo como contenedor directo
del contenido que se representa en la pantalla. Por ejemplo, un elemento Paragraph (elemento de
bloque) puede contener un elemento Run (elemento inline), pero es Run el que contiene en realidad el
texto que se representa en la pantalla.
A continuacin se describe brevemente cada una de las clases de estas dos categoras.
Clases derivadas de bloque
Paragraph
Paragraph se utiliza normalmente para agrupar el contenido en un prrafo. El uso ms sencillo y comn de
Paragraph es crear un prrafo de texto.
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Paragraph>
Some paragraph text.
</Paragraph>
</FlowDocument>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace SDKSample
{
public partial class ParagraphExample : Page
{
public ParagraphExample()
{
// Create paragraph with some text.
Paragraph myParagraph = new Paragraph();
myParagraph.Inlines.Add(new Run("Some paragraph text."));
// Create a FlowDocument and add the paragraph to it.
FlowDocument myFlowDocument = new FlowDocument();
myFlowDocument.Blocks.Add(myParagraph);
this.Content = myFlowDocument;
}
}
}
Sin embargo, tambin puede contener otros elementos inline derivados, como comprobar a continuacin.
Seccin
Section slo se utiliza para contener otros elementos derivados de Block. No aplica ningn formato
predeterminado a los elementos que contiene. Sin embargo, cualquier conjunto de valores establecidos en un
elemento Section se aplica a sus elementos secundarios. Asimismo, una seccin tambin le permite recorrer en
List
List se utiliza para crear una lista con vietas o numrica. Establezca la propiedad MarkerStyle en un valor de
enumeracin TextMarkerStyle para determinar el estilo de la lista. En el siguiente ejemplo se muestra cmo
crear una lista sencilla.
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<List>
<ListItem>
<Paragraph>
List Item 1
</Paragraph>
</ListItem>
<ListItem>
<Paragraph>
List Item 2
</Paragraph>
</ListItem>
<ListItem>
<Paragraph>
List Item 3
</Paragraph>
</ListItem>
</List>
</FlowDocument>
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Documents;
namespace SDKSample
{
public partial class ListExample : Page
{
public ListExample()
{
Item 1"));
Item 2"));
Item 3"));
the
}
}
Nota: List es el nico elemento dinmico que utiliza ListItemCollection para administrar los elementos
secundarios.
Table
Table se utiliza para crear una tabla. Table es similar al elemento Grid, pero tiene ms funciones, por lo que
requiere un mayor consumo de recursos. Dado que Grid es un elemento UIElement, no se puede utilizar en el
contenido dinmico a menos que est incluido en un elemento BlockUIContainer o InlineUIContainer.
Clases derivadas inline
Run
Run se utiliza para contener texto sin formato. Podra pensarse que los objetos Run se utilizan extensivamente
en el contenido dinmico; sin embargo, en el marcado no es necesario utilizar los elementos Run de forma
explcita. Por ejemplo, en el marcado siguiente, el primer elemento Paragraph especifica explcitamente el
elemento Run, mientras que el segundo no lo hace. Ambos prrafos generan el mismo resultado.
<Paragraph>
<Run>Paragraph that explicitly uses the Run element.</Run>
</Paragraph>
<Paragraph>
This Paragraph omits the the Run element in markup. It renders
the same as a Paragraph with Run used explicitly.
</Paragraph>
Nota: es necesario utilizar Run al crear o manipular documentos dinmicos mediante cdigo.
Span
Span agrupa otros elementos de contenido inline. No se aplica ninguna representacin inherente al contenido
dentro de un elemento Span. Sin embargo, los elementos que heredan de Span, incluyendo Hyperlink, Bold,
Italic y Underline, aplican formato al texto.
A continuacin se muestra un ejemplo de un objeto Span utilizado para incluir contenido inline, incluyendo
texto, un elemento Bold y un elemento Button.
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Paragraph>
Text before the Span. <Span Background="Red">Text within the Span is
red and <Bold>this text is inside the Span-derived element Bold.</Bold>
A Span can contain more then text, it can contain any inline content. For
example, it can contain a
<InlineUIContainer>
<Button>Button</Button>
</InlineUIContainer>
or other UIElement, a Floater, a Figure, etc.</Span>
</Paragraph>
</FlowDocument>
La captura de pantalla siguiente muestra cmo se representa este ejemplo.
InlineUIContainer
InlineUIContainer permite incrustar elementos UIElement (por ejemplo, un control como Button) en un
elemento de contenido Inline. Este elemento es el equivalente inline al elemento BlockUIContainer descrito
anteriormente. A continuacin se muestra un ejemplo que utiliza InlineUIContainer para insertar un control
Button inline en un elemento Paragraph.
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Paragraph>
Text to precede the button...
<!-- Set the BaselineAlignment property to "Bottom"
so that the Button aligns properly with the text. -->
<InlineUIContainer BaselineAlignment="Bottom">
<Button>Button</Button>
</InlineUIContainer>
Text to follow the button...
</Paragraph>
</FlowDocument>
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Documents;
namespace SDKSample
{
public partial class InlineUIContainerExample : Page
{
public InlineUIContainerExample()
{
Run run1 = new Run(" Text to precede the button... ");
Run run2 = new Run(" Text to follow the button... ");
// Create a new button to be hosted in the paragraph.
Button myButton = new Button();
myButton.Content = "Click me!";
// Create a new InlineUIContainer to contain the Button.
InlineUIContainer myInlineUIContainer = new InlineUIContainer();
// Set the BaselineAlignment property to "Bottom" so that the
// Button aligns properly with the text.
myInlineUIContainer.BaselineAlignment = BaselineAlignment.Bottom;
// Asign the button as the UI container's child.
myInlineUIContainer.Child = myButton;
// Create the paragraph and add content to it.
Paragraph myParagraph = new Paragraph();
myParagraph.Inlines.Add(run1);
myParagraph.Inlines.Add(myInlineUIContainer);
myParagraph.Inlines.Add(run2);
// Create a FlowDocument and add the paragraph to it.
FlowDocument myFlowDocument = new FlowDocument();
myFlowDocument.Blocks.Add(myParagraph);
this.Content = myFlowDocument;
}
}
}
Nota: no es necesario utilizar InlineUIContainer explcitamente en el marcado. Si lo omite, se crear de todas
formas un elemento InlineUIContainer al compilar el cdigo.
Figure y Floater
Figure y Floater se utilizan para incrustar contenido en documentos dinmicos con propiedades de posicin que
se pueden personalizar de forma independiente del flujo de contenido primario. Los elementos Figure o Floater
se utilizan a menudo para resaltar o recalcar partes de contenido, hospedar imgenes auxiliares u otro
contenido dentro del flujo de contenido principal, o bien para insertar contenido de relacin indirecta, como los
anuncios.
El ejemplo siguiente muestra cmo incrustar un elemento Figure en un prrafo de texto.
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Paragraph>
<Figure
Se puede determinar su posicin: puede establecer sus puntos de anclaje horizontales y verticales
para acoplarlo con respecto a la pgina, el contenido, la columna o el prrafo. Tambin puede utilizar
sus propiedades HorizontalOffset y VerticalOffset para especificar desplazamientos arbitrarios.
Se puede ajustar su tamao a varias columnas: puede establecer el alto y el ancho del elemento
Figure en mltiplos de los valores de alto o ancho de la pgina, el contenido o la columna. Observe que
en el caso de la pgina y del contenido, no se permiten mltiplos mayores que 1. Por ejemplo, puede
establecer el ancho de Figure en "0,5 page", "0,25 content" o "2 Column". Tambin puede establecer
el alto y el ancho en valores absolutos de pxel.
Elemento Floater:
Floater pagina: si su contenido en el ancho especificado se extiende ms all del alto de una columna,
el elemento Floater se parte y salta a la siguiente columna, la siguiente pgina, etc.
Figure se presta especialmente para contenido independiente cuyo tamao y posicin desea controlar, ya que le
da la seguridad de que el contenido se ajustar al tamao especificado. Floater se presta especialmente para
contenido que fluye ms libremente y de manera similar al contenido de la pgina principal, pero que es
independiente de este ltimo.
LineBreak
LineBreak origina un salto de lnea en el contenido dinmico. El siguiente ejemplo muestra el uso de LineBreak.
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Paragraph>
Before the LineBreak in Paragraph.
<LineBreak />
After the LineBreak in Paragraph.
<LineBreak/><LineBreak/>
After two LineBreaks in Paragraph.
</Paragraph>
<Paragraph>
<LineBreak/>
</Paragraph>
<Paragraph>
After a Paragraph with only a LineBreak in it.
</Paragraph>
</FlowDocument>
La captura de pantalla siguiente muestra cmo se representa este ejemplo.
Esto agrega un elemento Run al elemento InlineCollection del objeto Paragraph. Esto es lo mismo que el
elemento Run implcito incluido en un objeto Paragraph en el marcado:
<Paragraph>
Some Text
Como ejemplo de uso del elemento BlockCollection, el ejemplo siguiente crea un nuevo elemento Section y, a
continuacin, utiliza el mtodo Add para agregar un nuevo elemento Paragraph al contenido de Section.
Section secx = new Section();
secx.Blocks.Add(new Paragraph(new Run("A bit of text content...")));
Adems de agregar elementos a una coleccin dinmica, tambin se pueden quitar. En el siguiente ejemplo se
elimina el ltimo elemento Inline de Span.
spanx.Inlines.Remove(spanx.Inlines.LastInline);
En el siguiente ejemplo se borra todo el contenido (los elementos Inline) de Span.
spanx.Inlines.Clear();
Al trabajar con contenido dinmico mediante programacin, probablemente realizar un uso extensivo de estas
colecciones.
Que un elemento dinmico utilice un elemento InlineCollection (Inlines) o un elemento BlockCollection (Blocks)
para contener sus elementos secundarios depender de qu tipo de elementos secundarios (Block o Inline)
puedan ser incluidos en el elemento primario. Las reglas de contencin para los elementos de contenido
dinmico se resumen en el esquema de contenido de la seccin siguiente.
Nota: existe un tercer tipo de coleccin utilizado con el contenido dinmico, ListItemCollection, pero esta
coleccin slo se usa con un elemento List. Adems, hay varias colecciones que se utilizan con Table.
Esquema de contenido
Dado el nmero de elementos de contenido dinmico diferentes que existen, puede resultar muy complicado
efectuar un seguimiento del tipo de elementos secundarios que puede contener un elemento. El diagrama
siguiente resume las reglas de contencin para los elementos dinmicos. Las flechas representan las posibles
relaciones entre elementos primarios/secundarios.
Como se puede ver en el diagrama anterior, los elementos secundarios permitidos para un elemento no estn
determinados necesariamente por el hecho de que ste sea un elemento Block o Inline. Por ejemplo, un objeto
Span (un elemento Inline) slo puede tener elementos secundarios Inline, mientras que un objeto Figure
(tambin un elemento Inline) slo puede tener elementos secundarios Block. Por consiguiente, un diagrama es
til para determinar rpidamente qu elemento puede incluirse en otro. Como ejemplo, utilicemos el diagrama
para determinar cmo construir el contenido dinmico de un elemento RichTextBox.
1. Un objeto RichTextBox debe contener un elemento FlowDocument, que a su vez debe contener un objeto
derivado de Block. A continuacin se muestra el segmento correspondiente del diagrama anterior.
Las ilustraciones siguientes muestran cmo se representan las decoraciones Lnea alta, Lnea base y
Subrayado, respectivamente.
Tipografa
La propiedad Typography la expone la mayora del contenido relacionado con el flujo, como TextElement,
FlowDocument, TextBlock y TextBox. Esta propiedad se utiliza para controlar caractersticas/variaciones
tipogrficas del texto (por ejemplo, maysculas pequeas o grandes, generacin de superndices y subndices,
etc.).
En el ejemplo siguiente se muestra cmo establecer el atributo Typography usando Paragraph como elemento
de ejemplo.
<Paragraph
TextAlignment="Left"
FontSize="18"
FontFamily="Palatino Linotype"
Typography.NumeralStyle="OldStyle"
Typography.Fraction="Stacked"
Typography.Variants="Inferior">
<Run>
This text has some altered typography characteristics. Note
that use of an open type font is necessary for most typographic
properties to be effective.
</Run>
<LineBreak/><LineBreak/>
<Run>
0123456789 10 11 12 13
</Run>
<LineBreak/><LineBreak/>
<Run>
1/2 2/3 3/4
</Run>
</Paragraph>
En la ilustracin siguiente se muestra cmo se representa este ejemplo.
En contraste, en la ilustracin siguiente se muestra cmo se representa un ejemplo similar con propiedades
tipogrficas predeterminadas.
Como se puede observar en el diagrama anterior, los elementos secundarios que se permiten para un elemento
no vienen determinados necesariamente por el hecho de si una clase se deriva de la clase Block o de una clase
Inline. Por ejemplo, Span (una clase derivada de Inline) nicamente puede tener elementos secundarios Inline,
pero una clase Figure (tambin derivada de Inline) nicamente puede tener elementos secundarios Block. Por
consiguiente, un diagrama es til para determinar rpidamente qu elemento puede incluirse en otro. Como
Un objeto RichTextBox debe contener un elemento FlowDocument, que a su vez debe contener un
objeto derivado de Block. A continuacin, se muestra el segmento correspondiente del diagrama
anterior.
Segn el diagrama, hay varios elementos Block entre los que elegir, incluidos Paragraph, Section,
Table, List y BlockUIContainer (vea las clases derivadas de Block en el diagrama anterior).
Supongamos que deseamos un elemento Table. Segn el diagrama anterior, un objeto Table incluye
un elemento TableRowGroup que contiene elementos TableRow, que a su vez contienen elementos
TableCell que incluyen un objeto derivado de Block. A continuacin se muestra el segmento
correspondiente para el elemento Table tomado del diagrama anterior.
De nuevo, se requieren uno o ms elementos Block debajo de un elemento TableCell. Para facilitar el
proceso, coloquemos texto dentro de la celda. Podemos hacerlo utilizando un objeto Paragraph con un
elemento Run. A continuacin se muestran los segmentos correspondientes del diagrama que
demuestran que un objeto Paragraph puede aceptar un elemento Inline y que un objeto Run (un
elemento Inline) slo puede aceptar texto sin formato.
Puede manipular estas colecciones (agregar o quitar elementos) utilizando las propiedades respectivas de
Inlines, Blocks y ListItems. En los ejemplos siguientes se muestra cmo manipular el contenido de un objeto
Span mediante la propiedad Inlines.
Nota:
El objeto Table utiliza varias colecciones para manipular su contenido, pero no se abordan aqu.
En el ejemplo siguiente se crea un nuevo objeto Span y, a continuacin, se utiliza el mtodo Add para agregar
dos series de texto como elementos de contenido secundarios de Span.
Span spanx = new Span();
spanx.Inlines.Add(new Run("A bit of text content..."));
spanx.Inlines.Add(new Run("A bit more text content..."));
En el ejemplo siguiente se crea un nuevo elemento Run y se inserta al principio de Span.
Run runx = new Run("Text to insert...");
spanx.Inlines.InsertBefore(spanx.Inlines.FirstInline, runx);
En el siguiente ejemplo se elimina el ltimo elemento Inline de Span.
spanx.Inlines.Remove(spanx.Inlines.LastInline);
En el siguiente ejemplo se borra todo el contenido (los elementos Inline) de Span.
spanx.Inlines.Clear();
Tipos que comparten este modelo de contenido
Los tipos siguientes heredan de la clase TextElement y se utilizan para mostrar el contenido descrito en esta
informacin general.
Bold, Figure, Floater, Hyperlink, InlineUIContainer, Italic, LineBreak, List, ListItem, Paragraph, Run, Section,
Span, Table, Underline.
Observe que esta lista incluye nicamente los tipos no abstractos distribuidos con Windows SDK. Puede utilizar
otros tipos que heredan de TextElement.
BlockUIContainer
List
Paragraph
Section
Table
Nota:
Los elementos TableCell no pueden hospedar directamente contenido de texto.
Nota:
Table es similar al elemento Grid pero tiene ms funciones y, por consiguiente, requiere mayor consumo de
recursos.
En el ejemplo siguiente se define una tabla simple de 2 x 3, con XAML.
<!-Table is a Block element, and as such must be hosted in a container
for Block elements. FlowDocument provides such a container.
-->
<FlowDocument>
<Table>
<!-This table has 3 columns, each described by a TableColumn
element nested in a Table.Columns collection element.
-->
<Table.Columns>
<TableColumn />
<TableColumn />
<TableColumn />
</Table.Columns>
<!-This table includes a single TableRowGroup which hosts 2 rows,
each described by a TableRow element.
-->
<TableRowGroup>
<!-Each of the 2 TableRow elements hosts 3 cells, described by
TableCell elements.
-->
<TableRow>
<TableCell>
<!-TableCell elements may only host elements derived from Block.
In this example, Paragaph elements serve as the ultimate content
containers for the cells in this table.
-->
<Paragraph>Cell at Row 1 Column 1</Paragraph>
</TableCell>
Contencin de tablas
Table se deriva del elemento Block y cumple las reglas comunes para los elementos de nivel de bloque, Block.
Cualquiera de los elementos siguientes puede contener un elemento Table:
FlowDocument
TableCell
ListBoxItem
ListViewItem
Section
Floater
Figure
Agrupaciones de filas
El elemento TableRowGroup proporciona una manera de agrupar filas arbitrariamente dentro de una tabla;
cada fila de una tabla debe pertenecer a una agrupacin de filas. Las filas dentro de un grupo de filas
comparten a menudo una finalidad comn y se les puede asignar un estilo como grupo. Una costumbre habitual
para las agrupaciones de filas es separar las filas que tienen una finalidad especial, como ttulos, encabezados y
filas del pie de pgina, del contenido principal incluido en la tabla.
En el ejemplo siguiente se utiliza XAML para definir una tabla con filas de encabezado y pie de pgina con
estilo.
<Table>
<Table.Resources>
<!-- Style for header/footer rows. -->
<Style x:Key="headerFooterRowStyle" TargetType="{x:Type TableRowGroup}">
<Setter Property="FontWeight" Value="DemiBold"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Background" Value="LightGray"/>
</Style>
<!-- Style for data rows. -->
<Style x:Key="dataRowStyle" TargetType="{x:Type TableRowGroup}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontStyle" Value="Italic"/>
</Style>
</Table.Resources>
<Table.Columns>
<TableColumn/> <TableColumn/> <TableColumn/> <TableColumn/>
</Table.Columns>
<!-- This TableRowGroup hosts a header row for the table. -->
<TableRowGroup Style="{StaticResource headerFooterRowStyle}">
<TableRow>
<TableCell/>
<TableCell><Paragraph>Gizmos</Paragraph></TableCell>
<TableCell><Paragraph>Thingamajigs</Paragraph></TableCell>
<TableCell><Paragraph>Doohickies</Paragraph></TableCell>
Table
2.
TableColumn
3.
TableRowGroup
4.
TableRow
5.
TableCell
Estudie el ejemplo siguiente, en el que se definen los colores de fondo para cada uno de estos elementos
dentro de una tabla.
<Table Background="Yellow">
<Table.Columns>
<TableColumn/>
<TableColumn Background="LightGreen"/>
<TableColumn/>
</Table.Columns>
<TableRowGroup>
<TableRow>
<TableCell/><TableCell/><TableCell/>
</TableRow>
</TableRowGroup>
<TableRowGroup Background="Tan">
<TableRow>
<TableCell/><TableCell/><TableCell/>
</TableRow>
<TableRow Background="LightBlue">
<TableCell/><TableCell Background="Purple"/><TableCell/>
</TableRow>
<TableRow>
<TableCell/><TableCell/><TableCell/>
</TableRow>
</TableRowGroup>
<TableRowGroup>
Observe que la coleccin Columns de la tabla utiliza la indizacin estndar basada en cero.
' Create 6 columns and add them to the table's Columns collection.
Dim numberOfColumns = 6
Dim x
For x = 0 To numberOfColumns
table1.Columns.Add(new TableColumn())
' Set alternating background colors for the middle colums.
If x Mod 2 = 0 Then
table1.Columns(x).Background = Brushes.Beige
Else
table1.Columns(x).Background = Brushes.LightSteelBlue
End If
Next x
Luego, se crea una fila de ttulo y se agrega a la tabla tras aplicarle formato. La fila de ttulo contiene una sola
celda que abarca las seis columnas de la tabla.
' Create and add an empty TableRowGroup to hold the table's Rows.
table1.RowGroups.Add(new TableRowGroup())
' Add the first (title) row.
table1.RowGroups(0).Rows.Add(new TableRow())
' Alias the current working row for easy reference.
Dim currentRow As New TableRow()
currentRow = table1.RowGroups(0).Rows(0)
' Global formatting for the title row.
currentRow.Background = Brushes.Silver
currentRow.FontSize = 40
currentRow.FontWeight = System.Windows.FontWeights.Bold
' Add the header row with content,
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("2004 Sales Project"))))
' and set the row to span all 6 columns.
currentRow.Cells(0).ColumnSpan = 6
Despus, se crea una fila de encabezado y se agrega a la tabla, y se crean y rellenan con contenido las celdas
de la fila de encabezado.
' Add the second (header) row.
table1.RowGroups(0).Rows.Add(new TableRow())
currentRow = table1.RowGroups(0).Rows(1)
' Global formatting for the header row.
currentRow.FontSize = 18
currentRow.FontWeight = FontWeights.Bold
' Add cells with content to the second row.
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
Run("Product"))))
Run("Quarter 1"))))
Run("Quarter 2"))))
Run("Quarter 3"))))
Run("Quarter 4"))))
Run("TOTAL"))))
En este momento, se crea una fila de datos y se agrega a la tabla, y se crean y rellenan con contenido las
celdas de esta fila. Generar esta fila es similar a generar la fila de encabezado, con un formato ligeramente
diferente.
' Add the third row.
table1.RowGroups(0).Rows.Add(new TableRow())
currentRow = table1.RowGroups(0).Rows(2)
' Global formatting for the row.
currentRow.FontSize = 12
currentRow.FontWeight = FontWeights.Normal
' Add cells with content to the third row.
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
' Bold the first cell.
currentRow.Cells(0).FontWeight = FontWeights.Bold
Run("Widgets"))))
Run("$50,000"))))
Run("$55,000"))))
Run("$60,000"))))
Run("$65,000"))))
Run("$230,000"))))
Por ltimo, se crea una fila de pie de pgina, se agreg y se le da formato. Al igual que la fila de ttulo, el pie de
pgina contiene una sola celda que abarca las seis columnas de la tabla.
table1.RowGroups(0).Rows.Add(new TableRow())
currentRow = table1.RowGroups(0).Rows(4)
' Global formatting for the footer row.
currentRow.Background = Brushes.LightGray
currentRow.FontSize = 18
currentRow.FontWeight = System.Windows.FontWeights.Normal
' Add the header row with content,
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Projected 2004 Revenue:
$810,000"))))
' and set the row to span all 6 columns.
Two adjacent
Run("Product"))))
Run("Quarter 1"))))
Run("Quarter 2"))))
Run("Quarter 3"))))
Run("Quarter 4"))))
Run("TOTAL"))))
En este momento, se crea una fila de datos y se agrega a la tabla, y se crean y rellenan con contenido las
celdas de esta fila. Generar esta fila es similar a generar la fila de encabezado, con un formato ligeramente
diferente.
' Add the third row.
table1.RowGroups(0).Rows.Add(new TableRow())
currentRow = table1.RowGroups(0).Rows(2)
' Global formatting for the row.
currentRow.FontSize = 12
currentRow.FontWeight = FontWeights.Normal
' Add cells with content to the third row.
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
currentRow.Cells.Add(new TableCell(new Paragraph(new
Run("Widgets"))))
Run("$50,000"))))
Run("$55,000"))))
Run("$60,000"))))
Run("$65,000"))))
Run("$230,000"))))
En contraste, en la ilustracin siguiente se muestra cmo se representa un ejemplo similar con propiedades
tipogrficas predeterminadas.
Cuando TextTrimming se establece en WordEllipsis, el texto se recorta y se contina con puntos suspensivos
al final de la primera palabra completa ms prxima al borde de recorte. Este valor no mostrar palabras
parcialmente recortadas, pero no suele recortar el texto tan cerca del borde de recorte como el valor
CharacterEllipsis. En la ilustracin siguiente se muestra el efecto de este valor en el objeto TextBlock definido
anteriormente.
Cuando TextTrimming se establece en None, no se recorta el texto. En este caso, el texto se corta
simplemente en el lmite del contenedor de texto primario. En la ilustracin siguiente se muestra el efecto de
este valor en un objeto TextBlock similar al definido anteriormente.
Figure
Floater
ListItem
Section
TableCell
En estos ejemplos se utiliza Section como elemento de contenido dinmico, pero estas tcnicas son aplicables a
todos los elementos que hospedan una coleccin de elementos de contenido dinmico.
Ejemplo
En el ejemplo siguiente se crea un nuevo objeto Section y, a continuacin, se utiliza el mtodo Add para
agregar un nuevo prrafo al contenido de Section.
Section secx = new Section();
secx.Blocks.Add(new Paragraph(new Run("A bit of text content...")));
En el ejemplo siguiente se crea un nuevo elemento Paragraph y se inserta al principio de Section.
Paragraph parx = new Paragraph(new Run("Text to insert..."));
secx.Blocks.InsertBefore(secx.Blocks.FirstBlock, parx);
En el ejemplo siguiente se obtiene el nmero de elementos Block de nivel superior contenidos en Section.
int countTopLevelBlocks = secx.Blocks.Count;
En el siguiente ejemplo se elimina el ltimo elemento Block de Section.
secx.Blocks.Remove(secx.Blocks.LastBlock);
En el siguiente ejemplo se borra todo el contenido (los elementos Block) de Section.
secx.Blocks.Clear();
Bold
Hyperlink
Italic
Paragraph
Span
Underline
En estos ejemplos se utiliza Span como elemento de contenido dinmico, pero estas tcnicas son aplicables a
todos los elementos o controles que hospedan una coleccin InlineCollection.
Ejemplo
En el ejemplo siguiente se crea un nuevo objeto Span y, a continuacin, utiliza el mtodo Add para agregar dos
series de texto como elementos de contenido secundarios de Span.
Span spanx = new Span();
spanx.Inlines.Add(new Run("A bit of text content..."));
spanx.Inlines.Add(new Run("A bit more text content..."));
En el ejemplo siguiente se crea un nuevo elemento Run y se inserta al principio de Span.
Run runx = new Run("Text to insert...");
spanx.Inlines.InsertBefore(spanx.Inlines.FirstInline, runx);
En el ejemplo siguiente se obtiene el nmero de elementos Inline de nivel superior contenidos en Span.
int countTopLevelInlines = spanx.Inlines.Count;
En el siguiente ejemplo se elimina el ltimo elemento Inline de Span.
spanx.Inlines.Remove(spanx.Inlines.LastInline);
En el siguiente ejemplo se borra todo el contenido (los elementos Inline) de Span.
spanx.Inlines.Clear();
Elemento Bold
Atributo BreakPageBefore
Atributo FontSize
Elemento Italic
Elemento LineBreak
Elemento List
Elemento ListItem
Elemento Paragraph
Elemento Run
Elemento Section
Elemento Span
Atributo Variants (superndice y subndice)
Elemento Underline
Ejemplo
<FlowDocument
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Paragraph FontSize="18">Flow Format Example</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>
<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>
<Paragraph FontSize="18">More flow elements</Paragraph>
<Paragraph FontSize="15">Inline, font type and weight, and a List</Paragraph>
<List>
<ListItem><Paragraph>ListItem 1</Paragraph></ListItem>
<ListItem><Paragraph>ListItem 2</Paragraph></ListItem>
<ListItem><Paragraph>ListItem 3</Paragraph></ListItem>
<ListItem><Paragraph>ListItem 4</Paragraph></ListItem>
6.5. Tipografa
Windows Presentation Foundation (WPF) incluye compatibilidad con la presentacin enriquecida de contenido de
texto. En WPF se representa el texto utilizando Microsoft ClearType, que mejora su claridad y legibilidad. WPF
tambin admite las fuentes OpenType, que ofrecen funciones adicionales a las definidas por el formato
TrueType.
La canalizacin de representacin de texto completa puede acelerarse mediante hardware en el WPF, siempre
que el equipo cumpla los requisitos mnimos de hardware necesarios. La representacin que no se puede llevar
a cabo mediante hardware se realiza mediante software. La aceleracin de hardware afecta a todas las fases de
la canalizacin de representacin de texto, desde el almacenamiento de glifos individuales hasta la aplicacin
del algoritmo de mezcla de ClearType a la salida final mostrada, pasando por la composicin de glifos en
ejecuciones de glifos y la aplicacin de efectos.
Diagrama de la canalizacin de representacin de texto
Las letras floreadas son glifos decorativos en los que se utilizan adornos detallados que suelen asociarse a la
caligrafa. El texto siguiente muestra glifos normales y floreados de la fuente Pescadero.
Texto que utiliza glifos OpenType normales y floreados
Unicode para todo el texto. Ya no se requiere un juego de caracteres ni una pgina de cdigos para
regir el comportamiento y la seleccin de fuentes.
Tipos FontWeight, FontStretch, y FontStyle independientes para definir una clase FontFamily. De este
modo se proporciona mayor flexibilidad que en la programacin de Win32, donde se utilizan
combinaciones booleanas de cursiva y negrita para definir una familia de fuentes.
Los vnculos y el retroceso de fuente se incluyen en un archivo XML porttil, mediante la tecnologa de
fuentes compuestas. Las fuentes compuestas permiten la construccin de fuentes multilinges de
intervalo completo. Las fuentes compuestas tambin proporcionan un mecanismo que evita la
presentacin de glifos ausentes. Para obtener ms informacin, vea los comentarios de la clase
FontFamily.
Las fuentes internacionales se generan a partir de fuentes compuestas, mediante un grupo de fuentes
de un solo idioma. De este modo se ahorran costos de recursos al desarrollar fuentes para varios
idiomas.
Diseo e interfaz de usuario. Controles de texto comunes de la interfaz grfica de usuario (GUI).
Dibujo de texto ligero. Permite dibujar texto directamente en los objetos.
Formato de texto avanzado. Permite implementar un motor de texto personalizado.
En el ejemplo siguiente se muestra la segunda lnea de texto ajustada a una escala del 150% a lo largo del eje
X y la tercera lnea de texto ajustada a una escala del 150% a lo largo del eje Y.
Texto al que se ha aplicado ScaleTransform
TextEffect es un objeto auxiliar que permite tratar el texto como uno o ms grupos de caracteres en una
cadena de texto. En el ejemplo siguiente, tomado de Ejemplo TextEffect, se muestra un carcter individual al
que se aplica una rotacin. Cada carcter gira de manera independiente a intervalos de 1 segundo.
Puede convertir el texto con formato en objetos Geometry, lo que permite crear otros tipos de texto
visualmente interesante. Por ejemplo, podra crear un objeto Geometry basado en el contorno de una cadena
de texto.
Aplicacin de un contorno al texto mediante un pincel de degradado lineal
En los ejemplos siguientes se muestran varias maneras de crear efectos visuales interesantes modificando el
trazo, el relleno y el resaltado del texto convertido.
Ejemplo de cmo establecer el trazo y el relleno en diferentes colores
mediante
el
objeto
TextFormatter
otros
tipos
en
el
espacio
de
nombres
Recursos
Una tcnica til para obtener informacin sobre las caractersticas de OpenType es utilizar XamlPad para crear
un marcado que experimente con el uso de diversas propiedades tipogrficas.
Probar fuentes OpenType con XamlPad
En los dos ejemplos siguientes se compara la salida del representador ClearType anterior con la nueva versin
del procesador ClearType. La posicin de subpxel, que se muestra a la derecha, mejora en gran medida el
espaciado de los tipos en la pantalla, sobre todo en los tamaos pequeos donde la diferencia entre un subpxel
y un pxel entero representa una proporcin significativa de ancho del glifo. Observe que el espaciado entre las
letras es ms uniforme en la segunda imagen. Se aumenta significativamente la ventaja acumulativa de la
posicin de subpxel para el aspecto global de una pantalla de texto, lo que representa una evolucin
significativa en la tecnologa ClearType.
ClearType en Windows Presentation Foundation (WPF) proporciona el suavizado en el nivel de la direccin del
eje Y para suavizar los bordes escalonados. Es particularmente importante para mejorar la legibilidad en los
idiomas del este asitico, cuyos ideogramas tienen una cantidad casi igual de curvas horizontales y verticales
poco marcadas.
En el ejemplo siguiente se muestra el efecto del suavizado en la direccin del eje Y. En este caso, las partes
superior e inferior de la letra muestran una curva poco marcada.
Texto con suavizado (anti-aliasing) de ClearType en la direccin del eje y
Aceleracin de hardware
La tecnologa ClearType de Windows Presentation Foundation (WPF) puede aprovechar la aceleracin de
hardware para mejor el rendimiento y reducir la carga de la CPU, as como los requisitos de memoria del
sistema. ClearType utiliza los sombreadores de pxeles y la memoria de vdeo de la tarjeta grfica para
proporcionar una representacin ms rpida del texto, en especial cuando se utiliza la animacin.
ClearType no modifica en Windows Presentation Foundation (WPF) los valores de ClearType para todo el
sistema. Al deshabilitar ClearType en Windows, se establece el suavizado (anti-aliasing) de Windows
Presentation Foundation (WPF) en el modo de escala de grises. Adems, la tecnologa ClearType de Windows
Presentation Foundation (WPF) no modifica los valores de ClearType Tuner PowerToy.
Descripcin
Nivel de ClearType
Nivel gamma
Estructura de pxeles
Cualquier utilidad de configuracin externa que pueda hacer referencia a los valores del Registro identificados
de WPF para ClearType puede tener acceso a estos valores. Estos valores se pueden crear o modificar tambin
mediante el acceso directo a ellos utilizando el Editor del Registro de Windows.
Si los valores del Registro de WPF para ClearType no se establecen (que es el estado predeterminado), la
aplicacin WPF consulta los valores de suavizado de fuentes en la informacin de parmetros de sistema de
Windows.
ClearType Level
El nivel de ClearType permite ajustar la representacin de texto basndose en la sensibilidad y percepcin del
color de una persona. Para algunas personas, la representacin de texto que utiliza el mximo nivel de
ClearType no da lugar a la mejor experiencia de lectura.
Nota:
Las aplicaciones de WPF representan el texto en uno de estos dos modos: con y sin ClearType. Cuando el
texto se representa sin ClearType, se denomina representacin en escala de grises.
Nivel gamma
El nivel gamma hace referencia a la relacin no lineal entre el valor y la luminancia de un pxel. El valor gamma
debe corresponder a las caractersticas fsicas del dispositivo de pantalla; de lo contrario, la representacin
puede aparecer distorsionada. Por ejemplo, el texto puede aparecer demasiado ancho o estrecho, o puede
suceder que aparezcan franjas de color en los bordes de las astas de los glifos.
El nivel gamma es un valor entero comprendido entre 1000 y 2200. El nivel predeterminado es 1900.
Valor del Registro
La ubicacin de valor del Registro correspondiente al nivel gamma es un valor del equipo local que corresponde
a un nombre de dispositivo de pantalla concreto:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Avalon.Graphics\<displayName>
Para cada nombre de dispositivo de pantalla de un usuario, se define un valor DWORD de GammaLevel. En la
captura de pantalla siguiente se muestra el valor en el Editor del Registro para el nivel gamma.
Estructura de pxeles
La estructura de pxeles describe el tipo de pxeles que constituyen un dispositivo de pantalla. La estructura de
pxeles se define como uno de estos tres tipos:
Tipo
Valor
Descripcin
Plana
El dispositivo de pantalla no tiene ninguna estructura de pxeles. Esto significa que las
fuentes de iluminacin para cada color se expanden por igual sobre el rea de pxeles, lo
BGR
Nota:
Para los programadores que migran desde API de Win32, la tabla de la seccin Migracin de Win32
enumera los marcadores DrawText de Win32 y el equivalente aproximado en Windows Presentation
Foundation (WPF).
Razones para utilizar el texto con formato
WPF incluye varios controles para dibujar texto en la pantalla. Cada control se destina a un escenario diferente
y tiene su propia lista de caractersticas y limitaciones. En general, el elemento TextBlock se debe usar cuando
se necesita una compatibilidad de texto limitada, como una frase breve en una interfaz de usuario (UI). Label
se puede usar cuando se necesita una compatibilidad de texto mnima.
El objeto FormattedText proporciona ms caractersticas de formato de texto que los controles de texto de
Windows Presentation Foundation (WPF) y puede ser til en casos donde se desea utilizar el texto como
elemento decorativo.
Adems, el objeto FormattedText es til para crear objetos orientados a texto derivados de DrawingVisual.
DrawingVisual es una clase de dibujo ligera que se utiliza para representar formas, imgenes o texto.
Utilizar el objeto FormattedText
Para crear texto con formato, llame al constructor FormattedText para crear un objeto FormattedText. Una vez
creada la cadena de texto con formato inicial, puede aplicarle varios estilos de formato.
Utilice la propiedad MaxTextWidth para restringir el texto a un ancho especfico. El texto se ajustar
automticamente para evitar superar el ancho especificado. Utilice la propiedad MaxTextHeight para restringir
el texto a un alto especfico. El texto mostrar puntos suspensivos, "". para el texto que supera el alto
especificado.
Texto mostrado al que se ha aplicado el ajuste de lnea y los puntos suspensivos
Puede aplicar varios estilos de formato a uno o ms caracteres. Por ejemplo, podra llamar a los mtodos
SetFontSize y SetForegroundBrush para cambiar el formato de los cinco primeros caracteres del texto.
En el ejemplo de cdigo siguiente se crea un objeto FormattedText y, a continuacin, se aplican varios estilos
de formato al texto.
protected override void OnRender(DrawingContext drawingContext)
{
string testString = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed
do eiusmod tempor";
// Create the initial formatted text string.
FormattedText formattedText = new FormattedText(testString,
CultureInfo.GetCultureInfo("en-us"),FlowDirection.LeftToRight,
new Typeface("Verdana"),32,Brushes.Black);
// Set a maximum width and height. If the text overflows these values, an ellipsis
"..." appears.
formattedText.MaxTextWidth = 300; formattedText.MaxTextHeight = 240;
// Use a larger font size beginning at the first (zero-based) character and
continuing for 5 characters.
// The font size is calculated in terms of points -- not as device-independent
pixels.
formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5);
En los ejemplos siguientes se muestran varias maneras de crear efectos visuales interesantes modificando el
trazo, el relleno y el resaltado del texto convertido.
Ejemplo de cmo establecer el trazo y el relleno en diferentes colores
Cuando se convierte el texto en un objeto Geometry, deja de ser una coleccin de caracteres; no se pueden
modificar los caracteres de la cadena de texto. Sin embargo, se puede cambiar la apariencia del texto
convertido modificando sus propiedades de trazo y relleno. El trazo se refiere al contorno del texto convertido;
el relleno se refiere al rea situada dentro del contorno del texto convertido.
Tambin puede convertir el texto con formato en un objeto PathGeometry y utiliza el objeto para resaltar el
texto. Por ejemplo, puede aplicar una animacin al objeto PathGeometry para que la animacin siga el contorno
del texto con formato.
En el ejemplo siguiente se muestra texto con formato convertido en un objeto PathGeometry. Una elipse
animada sigue el trazado de los trazos del texto representado.
Esfera que sigue la geometra de trazado del texto
Puede crear otros usos interesantes para el texto con formato una vez convertido en un objeto PathGeometry.
Por ejemplo, puede mostrar en l un clip de vdeo.
Migracin de Win32
Las caractersticas de FormattedText para dibujar texto son similares a las de la funcin DrawText de Win32.
Para los programadores que migran desde la API de Win32, se enumeran en la tabla siguiente los marcadores
de DrawText de Win32 y su equivalente aproximado en Windows Presentation Foundation (WPF).
Marcador de DrawText
Equivalente
de WPF
DT_BOTTOM
Height
DT_CALCRECT
Height, Width
DT_CENTER
TextAlignment
DT_EDITCONTROL
Ninguno
DT_END_ELLIPSIS
Trimming
DT_EXPAND_TABS
Ninguno
DT_EXTERNALLEADING
Ninguno
DT_HIDEPREFIX
Ninguno
DT_LEFT
TextAlignment
DT_MODIFYSTRING
Ninguno
No se admite.
DT_NOCLIP
VisualClip
DT_NOFULLWIDTHCHARBREAK
Ninguno
No se admite.
DT_NOPREFIX
Ninguno
Notas
Ninguno
Utilice la propiedad
WordEllipsis.
Trimming
DT_PREFIX
Ninguno
DT_PREFIXONLY
Ninguno
No se admite.
DT_RIGHT
TextAlignment
DT_RTLREADING
FlowDirection
DT_SINGLELINE
Ninguno
DT_TABSTOP
Ninguno
DT_TOP
Height
DT_VCENTER
Height
DT_WORDBREAK
Ninguno
DT_WORD_ELLIPSIS
Trimming
Utilice la propiedad
WordEllipsis.
Trimming
con
con
el
el
valor
valor
El formateador de texto se utiliza para recuperar lneas del texto con formato del almacn de texto, que es una
implementacin de TextSource. Para ello, se crea en primer lugar una instancia del formateador de texto
utilizando el mtodo Create. Este mtodo crea una instancia del formateador de texto y establece los valores
mximos de alto y ancho de lnea. Una vez creada una instancia del formateador de texto, se inicia el proceso
de creacin de lneas llamando al mtodo FormatLine. TextFormatter vuelve a llamar al origen del texto para
recuperar los parmetros de texto y formato correspondientes a las ejecuciones de texto que componen una
lnea.
En el ejemplo siguiente se muestra el proceso de dar formato a un almacn de texto. Se utiliza el objeto
TextFormatter para recuperar lneas de texto del almacn de texto y, a continuacin, dar formato a la lnea de
texto para dibujar en DrawingContext.
Implementar el almacn de texto de cliente
Al extender el motor de formato de texto, se hace necesario implementar y administrar todos los aspectos del
almacn de texto. No es una labor trivial. El almacn de texto es responsable de realizar el seguimiento de las
propiedades de las ejecuciones de texto, las propiedades de prrafo, los objetos incrustados y otro contenido
similar. Adems, proporciona objetos TextRun individuales al formateador de texto, que este utiliza para crear
objetos TextLine.
Para administrar la virtualizacin del almacn de texto, este ltimo debe derivarse de TextSource. TextSource
define el mtodo utilizado por el formateador de texto para recuperar ejecuciones de texto del almacn de
texto. GetTextRun es el mtodo utilizado por el formateador de texto para recuperar las ejecuciones de texto
El ancho acumulado de las ejecuciones de texto supera el ancho de lnea mximo especificado en la
llamada para crear el formateador de texto o bien en la llamada al mtodo FormatLine del formateador
de texto.
Se devuelve una secuencia Unicode de nueva lnea, como "CF", "LF" o "CRLF".
Uso
TextCharacters
TextEmbeddedObject
TextEndOfLine
Ejecucin de texto especializada que se usa para marcar el fin de una lnea.
TextEndOfParagraph
TextEndOfSegment
TextHidden
TextModifier
Ejecucin de texto especializada que se usa para modificar las propiedades de las
ejecuciones de texto de su mbito. El mbito se extiende hasta la siguiente
ejecucin de texto TextEndOfSegment coincidente, o hasta el siguiente
TextEndOfParagraph.
Se pueden crear subclases de cualquiera de los objetos TextRun predefinidos. Esto permite que el origen de
texto proporcione al formateador de texto ejecuciones de texto que incluyen datos personalizados.
En el siguiente ejemplo se muestra un mtodo GetTextRun. Este almacn de texto devuelve objetos TextRun al
formateador de texto para procesarlos.
Nota:
En este ejemplo, el almacn de texto proporciona las mismas propiedades de texto a todo el texto. Los
almacenes de texto avanzados deben implementar su propia administracin de intervalos, a fin de permitir
que caracteres individuales tengan propiedades diferentes.
Especificar propiedades de formato
Se da formato a los objetos TextRun utilizando propiedades proporcionadas por el almacn del texto. Estas
propiedades se proporcionan en dos tipos, TextParagraphProperties y TextRunProperties. TextParagraph
Properties administra propiedades de inclusin de prrafo como TextAlignment y FlowDirection. TextRun
Properties son propiedades que pueden ser diferentes para cada ejecucin de texto de un prrafo, como un
pincel de primer plano, Typeface y el tamao de fuente. Para implementar los tipos de propiedades de prrafos
Nota:
El SDK de Windows contiene un conjunto fuentes OpenType de muestra que puede utilizar con aplicaciones
Windows Presentation Foundation (WPF). Estas fuentes ofrecen la mayora de las caractersticas ilustradas
en el resto de este tema.
Extensiones tipogrficas avanzadas
Las tablas tipogrficas avanzadas (tablas de diseo OpenType) extienden la funcionalidad de fuentes con
contornos TrueType o CFF. Las fuentes de diseo OpenType contienen informacin adicional que extiende las
funciones de las fuentes para permitir tipografa internacional de alta calidad. La mayora de las fuentes
OpenType exponen solamente un subconjunto de las caractersticas OpenType disponibles. Las fuentes
OpenType ofrecen las caractersticas siguientes.
Asignacin enriquecida entre caracteres y glifos que admiten ligaduras, formas posicionales,
alternativas y otras sustituciones de fuentes.
Informacin explcita de alfabeto e idioma contenida en fuente, para que las aplicaciones de
procesamiento de textos puedan ajustar su comportamiento en consecuencia.
Las tablas de diseo OpenType se describen con ms detalle en la seccin "Tablas de archivos de fuentes" de la
especificacin de OpenType.
El resto de esta informacin general presenta la amplitud y flexibilidad de algunas de las caractersticas de
OpenType de inters visual que exponen las propiedades del objeto Typography.
Variantes
Las variantes se utilizan para representar diferentes estilos tipogrficos, tales como superndices y subndices.
En el ejemplo de marcado siguiente se muestra cmo se definen superndices para la fuente Palatino Linotype,
mediante propiedades del objeto Typography.
<Paragraph FontFamily="Palatino Linotype">
2<Run Typography.Variants="Superscript">3</Run>
14<Run Typography.Variants="Superscript">th</Run>
</Paragraph>
En el texto siguiente se muestran subndices para la fuente Palatino Linotype.
Texto que utiliza subndices OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen subndices para la fuente Palatino Linotype,
mediante propiedades del objeto Typography.
<Paragraph FontFamily="Palatino Linotype">
H<Run Typography.Variants="Subscript">2</Run>O
Footnote<Run Typography.Variants="Subscript">4</Run>
</Paragraph>
Usos decorativos de superndices y subndices
Tambin puede utilizar superndices y subndices para crear efectos decorativos con texto en maysculas y
minsculas. El texto siguiente muestra texto en superndices y subndices para la fuente Palatino Linotype.
Observe que no las maysculas no se ven afectadas.
Texto que utiliza superndices y subndices OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen superndices y subndices para la fuente
Palatino Linotype, mediante propiedades del objeto Typography.
<Paragraph FontFamily="Palatino Linotype" Typography.Variants="Superscript">
Chapter One
</Paragraph>
<Paragraph FontFamily="Palatino Linotype" Typography.Variants="Subscript">
Chapter One
</Paragraph>
Maysculas
Las maysculas son un conjunto de formatos tipogrficos que representan el texto en glifos con estilo de
mayscula. Normalmente, cuando el texto se representa todo en maysculas, el espaciado entre las letras
puede parecer demasiado apretado, y el peso y proporcin de las letras demasiado pesado. OpenType admite
varios formatos de estilo para las maysculas, entre los que estn las versales, las maysculas pequeas, los
ttulos y el espaciado de maysculas. Estos formatos permiten controlar el aspecto de las maysculas.
En el texto siguiente se muestran las letras maysculas estndar de la fuente Pescadero, seguidas de letras con
estilo "SmallCaps" y "AllSmallCaps". En este caso, se utiliza el mismo tamao de fuente para las tres palabras.
Texto que utiliza maysculas OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen las maysculas para Ejemplo Using OpenType
Fonts, mediante las propiedades del objeto Typography. Cuando se utiliza el formato "SmallCaps", se omite
cualquier letra mayscula inicial.
<Paragraph FontFamily="Pescadero" FontSize="48">
<Run>CAPITALS</Run>
En el ejemplo de marcado siguiente se muestra cmo se definen las maysculas de ttulos para la fuente
Pescadero, mediante las propiedades del objeto Typography.
<Paragraph FontFamily="Pescadero">
<Run Typography.Capitals="Titling">chapter one</Run>
</Paragraph>
Espaciado de maysculas
El espaciado de maysculas es una caracterstica que permite proporcionar ms espaciado cuando se utiliza
maysculas en todo el texto. Las letras maysculas estn diseadas para combinarse con letras minsculas. El
espaciado que parece correcto entre una letra mayscula y una minscula puede parecer demasiado apretado
cuando se utilizan todas las letras maysculas. El texto siguiente muestra el espaciado normal y de maysculas
para la fuente Pescadero.
Texto que utiliza espaciado de maysculas OpenType
En el ejemplo de marcado siguiente se muestra cmo se define el espaciado de maysculas para la fuente
Pescadero, mediante las propiedades del objeto Typography.
<Paragraph FontFamily="Pescadero">
<Run Typography.CapitalSpacing="True">CHAPTER ONE</Run>
</Paragraph>
Ligaduras
Las ligaduras son dos o ms glifos que forman un glifo nico para crear texto ms legible o atractivo. Las
fuentes OpenType admiten cuatro tipos de ligaduras:
Ligaduras estndar. Diseadas para mejorar la legibilidad. Las ligaduras estndar incluyen "fi", "fl" y
"ff".
En el texto siguiente se muestran los glifos de ligadura estndar para la fuente Pericles.
Texto que utiliza ligaduras estndar OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen los glifos de ligadura estndar para la fuente
Pericles, mediante propiedades del objeto Typography.
<Paragraph FontFamily="Pericles" Typography.StandardLigatures="True">
<Run Typography.StylisticAlternates="1">FI</Run>
<Run Typography.StylisticAlternates="1">FL</Run>
En el ejemplo de marcado siguiente se muestra cmo se definen glifos de ligadura discrecional para la fuente
Pericles, mediante propiedades del objeto Typography.
<Paragraph FontFamily="Pericles" Typography.DiscretionaryLigatures="True">
<Run Typography.StylisticAlternates="1">CO</Run>
<Run Typography.StylisticAlternates="1">LA</Run>
<Run Typography.StylisticAlternates="1">LE</Run>
<Run Typography.StylisticAlternates="1">LI</Run>
<Run Typography.StylisticAlternates="1">LL</Run>
<Run Typography.StylisticAlternates="1">LO</Run>
<Run Typography.StylisticAlternates="1">LU</Run>
</Paragraph>
De forma predeterminada, las fuentes OpenType de Windows Presentation Foundation (WPF) habilitan las
ligaduras estndar. Por ejemplo, si utiliza la fuente Palatino Linotype, las ligaduras estndar "fi", "ff" y "fl"
aparecern como un glifo de caracteres combinados. Observe que el par de caracteres de cada ligadura
estndar se toca entre s.
Texto que utiliza ligaduras estndar OpenType
No obstante, puede deshabilitar las caractersticas de ligadura estndar para que una ligadura estndar, tal
como "ff", se muestre como dos glifos independientes, en lugar de mostrarse como un glifo de caracteres
combinados.
Texto que utiliza ligaduras estndar OpenType deshabilitadas
En el ejemplo de marcado siguiente se muestra cmo deshabilitar glifos de ligadura estndar para la fuente
Palatino Linotype, mediante propiedades del objeto Typography.
<!-- Set standard ligatures to false in order to disable feature. -->
<Paragraph Typography.StandardLigatures="False" FontFamily="Palatino Linotype"
FontSize="72">
fi ff fl
</Paragraph>
Letras floreadas
Las letras floreadas son glifos decorativos en los que se utilizan adornos detallados que suelen asociarse a la
caligrafa. El texto siguiente muestra glifos normales y floreados de la fuente Pescadero.
Texto que utiliza glifos OpenType normales y floreados
Se utilizan a menudo como elementos decorativos en frases cortas, como los anuncios de eventos. En el texto
siguiente se utilizan glifos floreados para dar nfasis a las letras maysculas del nombre del evento.
Texto que utiliza letras floreadas OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen letras floreadas para una fuente, mediante
propiedades del objeto Typography.
<Paragraph FontFamily="Pescadero" TextBlock.TextAlignment="Center">
Wishing you a<LineBreak/>
<Run Typography.StandardSwashes="1" FontSize="36">Happy New Year!</Run>
</Paragraph>
Letras floreadas contextuales
Algunas combinaciones de glifos floreados pueden producir un aspecto poco atractivo, como un solapamiento
de los trazos descendentes en letras adyacentes. El uso de floreo contextual permite utilizar un glifo floreado
sustituto que ofrezca un mejor aspecto. En el texto siguiente se muestra la misma palabra antes y despus de
aplicar un floreo contextual.
Texto que utiliza floreos contextuales OpenType
En el ejemplo de marcado siguiente se muestra cmo se define un floreo contextual para la fuente Pescadero,
mediante propiedades del objeto Typography.
<Paragraph FontFamily="Pescadero" Typography.StandardSwashes="1">
Lyon <Run Typography.ContextualSwashes="1">L</Run>yon
</Paragraph>
Alternativas
Las alternativas son glifos que pueden sustituirse por un glifo estndar. Las fuentes OpenType, tales como la
fuente Pericles que se utiliza en los ejemplos siguientes, puede contener glifos alternativos que puede usar para
crear diferentes apariencias para el texto. En el texto siguiente se muestran glifos estndar para la fuente
Pericles.
Texto que utiliza glifos estndar OpenType
La fuente Pericles de OpenType contiene glifos adicionales que proporcionan alternativas estilsticas al conjunto
estndar de glifos. En el texto siguiente se muestran glifos de alternativas estilsticas.
Texto que utiliza alternativas estilsticas de glifos OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen glifos de alternativa estilstica para la fuente
Pericles, mediante propiedades del objeto Typography.
<Paragraph FontFamily="Pericles">
<Run Typography.StylisticAlternates="1">A</Run>NCIENT
GR<Run Typography.StylisticAlternates="1">EE</Run>K
MYTH<Run Typography.StylisticAlternates="1">O</Run>LOGY
</Paragraph>
En el siguiente texto se muestran varios otros glifos de alternativas estilsticas para la fuente Pericles.
Texto que utiliza alternativas estilsticas de glifos OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen estos otros glifos de alternativas estilsticas.
<Paragraph FontFamily="Pericles">
<Run Typography.StylisticAlternates="1">A</Run>
<Run Typography.StylisticAlternates="2">A</Run>
<Run Typography.StylisticAlternates="3">A</Run>
<Run Typography.StylisticAlternates="1">C</Run>
<Run Typography.StylisticAlternates="1">E</Run>
<Run Typography.StylisticAlternates="1">G</Run>
<Run Typography.StylisticAlternates="1">O</Run>
<Run Typography.StylisticAlternates="1">Q</Run>
<Run Typography.StylisticAlternates="1">R</Run>
En el ejemplo de marcado siguiente se muestra cmo se definen alternativas contextuales aleatorias para la
fuente Lindsey, mediante propiedades del objeto Typography.
<TextBlock FontFamily="Lindsey">
<Run Typography.ContextualAlternates="True">
a banana in a cabana
</Run>
</TextBlock>
Formularios histricos
Las formas histricas son convenciones tipogrficas utilizadas comnmente en el pasado. En el texto siguiente
se muestra la frase "Boston, Massachusetts" utilizando un formato histrico de glifos para la fuente Palatino
Linotype.
Texto que utiliza formas histricas de OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen formas histricas para la fuente Palatino
Linotype, mediante propiedades del objeto Typography.
<Paragraph FontFamily="Palatino Linotype">
<Run Typography.HistoricalForms="True">Boston, Massachusetts</Run>
</Paragraph>
Estilos numricos
Las fuentes OpenType admiten un gran nmero de caractersticas que se pueden utilizar con valores numricos
en texto.
Fracciones
Las fuentes OpenType admiten estilos para fracciones, tales como los de fraccin apilada y con barra.
En el texto siguiente se muestran estilos de fraccin para la fuente Palatino Linotype.
Texto que utiliza fracciones con barra y apiladas de OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen estilos de fraccin para la fuente Palatino
Linotype, mediante propiedades del objeto Typography.
<Paragraph FontFamily="Palatino Linotype" Typography.Fraction="Slashed">
1/8 1/4 3/8 1/2 5/8 3/4 7/8
</Paragraph>
<Paragraph FontFamily="Palatino Linotype" Typography.Fraction="Stacked">
1/8 1/4 3/8 1/2 5/8 3/4 7/8
</Paragraph>
Numerales de estilo antiguo
Las fuentes OpenType admiten un formato numeral de estilo antiguo. Este formato es til para mostrar
nmeros en estilos que ya no son estndar. El texto siguiente muestra una fecha del siglo XVIII en formato
numrico estndar en formato y antiguo con la fuente Palatino Linotype.
En el texto siguiente se muestran nmeros estndar para la fuente Palatino Linotype, seguidos por nmeros en
estilo antiguo.
Texto que utiliza conjuntos de nmeros de estilo antiguo de OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen nmeros de estilo antiguo para la fuente
Palatino Linotype, mediante las propiedades del objeto Typography.
<Paragraph FontFamily="Palatino Linotype">
<Run Typography.NumeralStyle="Normal">1234567890</Run>
<Run Typography.NumeralStyle="OldStyle">1234567890</Run>
</Paragraph>
Cifras proporcionales y tabulares
Las fuentes OpenType admiten una caracterstica de cifras proporcionales y tabulares para controlar la
alineacin de anchos al utilizar nmeros. Las cifras proporcionales tratan los nmeros como si tuvieran un
ancho diferente - "1" es ms estrecho que "5." Las cifras tabulares se tratan como nmeros de igual ancho para
que se alineen verticalmente, lo que aumenta la legibilidad de la informacin de tipo financiero.
En el texto siguiente se muestran dos cifras proporcionales en la primera columna con la fuente Miramonte.
Observe la diferencia de ancho entre los nmeros "5" y "1". La segunda columna muestra los mismos dos
valores numricos con los anchos ajustados utilizando la caracterstica de cifra tabular.
Texto que utiliza cifras proporcionales y tabulares de OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen las cifras proporcionales y tabulares para la
fuente Miramonte, mediante las propiedades del objeto Typography.
<TextBlock FontFamily="Miramonte">
<Run Typography.NumeralAlignment="Proportional">114,131</Run>
</TextBlock>
<TextBlock FontFamily="Miramonte">
<Run Typography.NumeralAlignment="Tabular">114,131</Run>
</TextBlock>
Cero cruzado
Las fuentes OpenType admiten un formato del numeral cero cruzado para dar nfasis a la diferencia entre la
letra "O" y el numeral "0". El numeral cero cruzado se utiliza a menudo para los identificadores en la
informacin financiera y comercial.
El texto siguiente muestra un identificador de orden con la fuente Miramonte. La primera lnea utiliza numerales
estndares. La segunda lnea utiliza numerales de cero cruzado para conseguir un mejor contraste con la letra
"O" mayscula.
Texto que utiliza nmeros con cero cruzado de OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen nmeros con cero cruzado para la fuente
Miramonte, mediante propiedades del objeto Typography.
<Paragraph FontFamily="Miramonte">
<Run>Order #0048-OTC-390</Run>
<LineBreak/>
<Run Typography.SlashedZero="True">Order #0048-OTC-390</Run>
</Paragraph>
Clase Typography
El objeto Typography expone el conjunto de caractersticas compatibles con una fuente OpenType. Si establece
las propiedades de Typography en marcado, puede crear fcilmente documentos que saquen partido de las
caractersticas de OpenType.
En el texto siguiente se muestran las letras maysculas estndar de la fuente Pescadero, seguidas de letras con
estilo "SmallCaps" y "AllSmallCaps". En este caso, se utiliza el mismo tamao de fuente para las tres palabras.
Texto que utiliza maysculas OpenType
En el ejemplo de marcado siguiente se muestra cmo se definen las maysculas para la fuente Pescadero,
mediante las propiedades del objeto Typography. Cuando se utiliza el formato "SmallCaps", se omite cualquier
letra mayscula inicial.
<Paragraph FontFamily="Pescadero" FontSize="48">
<Run>CAPITALS</Run>
<Run Typography.Capitals="SmallCaps">Capitals</Run>
<Run Typography.Capitals="AllSmallCaps">Capitals</Run>
</Paragraph>
En el ejemplo de cdigo siguiente se realiza la misma tarea que en el ejemplo de marcado anterior.
MyParagraph.FontFamily = new FontFamily("Pescadero");
MyParagraph.FontSize = 48;
Run run_1 = new Run("CAPITALS ");
MyParagraph.Inlines.Add(run_1);
Run run_2 = new Run("Capitals ");
run_2.Typography.Capitals = FontCapitals.SmallCaps;
MyParagraph.Inlines.Add(run_2);
Run run_3 = new Run("Capitals");
run_3.Typography.Capitals = FontCapitals.AllSmallCaps;
MyParagraph.Inlines.Add(run_3);
MyParagraph.Inlines.Add(new LineBreak());
Propiedades de la clase Typography
En la tabla siguiente se presenta una lista de las propiedades, valores y configuraciones predeterminadas del
objeto Typography.
Property
Valores
Valor predeterminado
AnnotationAlternates
Capitals
FontCapitals.Normal
CapitalSpacing
Boolean
False
CaseSensitiveForms
Boolean
False
ContextualAlternates
Boolean
Trae
ContextualLigatures
Boolean
Trae
ContextualSwashes
DiscretionaryLigatures
Boolean
False
EastAsianExpertForms
Boolean
False
EastAsianLanguage
FontEastAsianLanguage.Normal
EastAsianWidths
FontEastAsianWidths.Normal
Fraction
FontFraction.Normal
HistoricalForms
Boolean
False
HistoricalLigatures
Boolean
False
Kerning
Boolean
Trae
MathematicalGreek
Boolean
False
NumeralAlignment
FontNumeralAlignment.Normal
NumeralStyle
Boolean
FontNumeralStyle.Normal
SlashedZero
Bolean
false
StandardLigatures
Bolean
true
StandardSwashes
StylisticAlternates
Variants
FontVariants.Normal
Bits de permiso de incrustacin de fuentes: las aplicaciones de WPF no comprueban ni aplican ningn
bit de permiso de incrustacin de fuentes.
Fuentes del sitio de origen: las aplicaciones de WPF no permiten las referencias de fuente a
identificador de recursos uniforme (URI) http o ftp.
URI absoluto con la notacin "pack:": las aplicaciones de WPF no permiten crear un objeto FontFamily
mediante programacin que utilice "pack:" como parte de la referencia absoluta de identificador de
recursos uniforme (URI) a una fuente. Por ejemplo, "pack://application:,,,/resources/#Pericles Light"
es una referencia no vlida a una fuente.
En los casos en que exista una referencia incorrecta, la aplicacin recurre a una fuente disponible.
Nota:
Ascender es un proveedor de productos avanzados de fuentes especializado en el diseo, la programacin y
las licencias de fuentes.
Tener acceso a las fuentes OpenType de ejemplo
Las fuentes OpenType de ejemplo se utilizan como recursos en el Ejemplo Using OpenType Fonts. En este
ejemplo se muestra el contenido de texto hospedado en FlowDocumentReader, que admite bsquedas,
navegacin, paginacin y ajuste de contenidos.
Ejemplo de fuentes OpenType
Archivo
Kootenay
Kooten.ttf
Lindsey
Linds.ttf
Miramonte
Miramo.ttf
Miramonte Bold
Miramob.ttf
Pericles
Peric.ttf
Pericles Light
Pericl.ttf
Pescadero
Pesca.ttf
Pescadero Bold
Pescab.ttf
Nota:
Como programador, es su responsabilidad asegurarse de disponer de los derechos de licencia necesarios
para cualquier fuente que incruste en una aplicacin o redistribuya de cualquier otro modo.
Una vez las fuentes se encuentren en su equipo, puede mostrar un conjunto representativo de caracteres en
varios tamaos de fuente haciendo doble clic en el nombre del archivo de fuente en el subdirectorio. En la
captura de pantalla siguiente se muestra el resultado que se presenta para el archivo de la fuente Lindsey,
Linds.ttf.
Mostrar la fuente Lindsey
6.5.7. Glifos
Los glifos son una representacin de bajo nivel de un carcter que se va a dibujar en pantalla. Windows
Presentation Foundation (WPF) proporciona acceso directo a los glifos para los clientes que desean interceptar y
conservar el texto despus de darle formato.
2.
Escenarios de impresin.
3.
Nota:
Glyphs y GlyphRun se han diseado para la presentacin de documentos de formato fijo y escenarios de
impresin. Windows Presentation Foundation (WPF) proporciona varios elementos para escenarios
generales de diseo e interfaz de usuario (UI), como Label y TextBlock.
Objeto GlyphRun
El objeto GlyphRun representa una secuencia de glifos de un solo tipo de letra de una nica fuente en un solo
tamao y con un nico estilo de representacin.
El objeto GlyphRun incluye detalles de la fuente, como la propiedad Indices del glifo y las posiciones de glifo
individuales. Adems, incluye los puntos de cdigo originales de Unicode a partir de los que se gener la
ejecucin, informacin de asignacin de desplazamiento de bfer de carcter a glifo, y marcadores por glifo y
por carcter.
Descripcin
FontUri
FontRenderingEmSize
StyleSimulations
BidiLevel
Especifica el nivel del diseo bidireccional. Los nmeros pares y el cero significan
que el diseo es de izquierda a derecha; los valores impares representan un
diseo de derecha a izquierda.
Propiedad Indices
La propiedad Indices es una cadena de especificaciones del glifo. En aquellos casos en que una secuencia de
glifos forma un clster nico, la especificacin del primer glifo del clster va precedida por un a especificacin
del nmero de glifos y puntos de cdigo se combinan para constituir el clster. La propiedad Indices recopila en
una cadena las propiedades siguientes.
ndices de glifo
Anchos de avance del glifo
Combinacin de vectores de asociacin de glifos
Asignacin del clster de los puntos de cdigo a los glifos
Marcadores de glifo
Marcado de glifos
En el ejemplo de cdigo siguiente se muestra cmo se utilizan diversas propiedades del elemento Glyphs en
XAML.
<!-- The example shows how to use different property settings of Glyphs objects. -->
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="PowderBlue" >
<Glyphs
FontUri
= "C:\WINDOWS\Fonts\ARIAL.TTF"
FontRenderingEmSize = "36"
StyleSimulations
= "ItalicSimulation"
UnicodeString
= "Hello World!"
Fill
= "SteelBlue"
OriginX
= "50"
OriginY
= "75" />
<!-- "Hello World!" with default kerning -->
<Glyphs
FontUri
= "C:\WINDOWS\Fonts\ARIAL.TTF"
FontRenderingEmSize = "36"
UnicodeString
= "Hello World!"
Fill
= "Maroon"
OriginX
= "50"
OriginY
= "150" />
<!-- "Hello World!" with explicit character widths for proportional font -->
<Glyphs
FontUri
= "C:\WINDOWS\Fonts\ARIAL.TTF"
FontRenderingEmSize = "36"
UnicodeString
= "Hello World!"
Indices
= ",80;,80;,80;,80;,80;,80;,80;,80;,80;,80;,80"
Fill
= "Maroon"
OriginX
= "50"
OriginY
= "225" />
<!-- "Hello World!" with fixed-width font -->
<Glyphs
FontUri
= "C:\WINDOWS\Fonts\COUR.TTF"
FontRenderingEmSize = "36"
StyleSimulations
= "BoldSimulation"
UnicodeString
= "Hello World!"
Fill
= "Maroon"
OriginX
= "50"
OriginY
= "300" />
<!-- "Open file" without "fi" ligature -->
<Glyphs
FontUri
= "C:\WINDOWS\Fonts\TIMES.TTF"
FontRenderingEmSize = "36"
StyleSimulations
= "BoldSimulation"
UnicodeString
= "Open file"
Para agregar una decoracin al texto, cree un objeto TextDecoration y modifique sus propiedades. Utilice la
propiedad Location para especificar dnde aparecer la decoracin de texto, como un subrayado. Utilice la
propiedad Pen para especificar el aspecto de la decoracin de texto, como un relleno slido o un color de
degradado. Si no especifica un valor para la propiedad Pen, las decoraciones tienen como valor predeterminado
El objeto Hyperlink es un elemento de contenido dinmico insertado que permite hospedar hipervnculos dentro
del contenido dinmico. De manera predeterminada, Hyperlink utiliza un objeto TextDecoration para mostrar un
subrayado. Crear instancias de los objetos TextDecoration puede afectar intensamente al rendimiento, en
especial si hay muchos objetos Hyperlink. Si realiza un uso excesivo de elementos Hyperlink, puede ser
conveniente mostrar la lnea de subrayado nicamente al desencadenar un evento, como el evento MouseEnter.
En el ejemplo siguiente, el subrayado para el vnculo "My MSN" es dinmico: nicamente aparece cuando se
activa el evento MouseEnter.
Hipervnculos definidos con TextDecorations
Ejemplo
En el ejemplo de cdigo siguiente, una decoracin de texto de subrayado utiliza el valor de fuente
predeterminado.
// Use the default font values for the strikethrough text decoration.
private void SetDefaultStrikethrough()
{
// Set the underline decoration directly to the text block.
TextBlock1.TextDecorations = TextDecorations.Strikethrough;
}
<!-- Use the default font values for the strikethrough text decoration. -->
<TextBlock TextDecorations="Strikethrough" FontSize="36" >
The quick red fox
</TextBlock>
En el ejemplo de cdigo siguiente, se crea una decoracin de texto de subrayado con un pincel de color slido
para el lpiz.
// Use a Red pen for the underline text decoration.
private void SetRedUnderline()
{
// Create an underline text decoration. Default is underline.
TextDecoration myUnderline = new TextDecoration();
// Create a solid color brush pen for the text decoration.
myUnderline.Pen = new Pen(Brushes.Red, 1);
myUnderline.PenThicknessUnit = TextDecorationUnit.FontRecommended;
// Set the underline decoration to a TextDecorationCollection and add it to the text
block.
TextDecorationCollection myCollection = new TextDecorationCollection();
myCollection.Add(myUnderline);
TextBlock2.TextDecorations = myCollection;
}
<!-- Use a Red pen for the underline text decoration -->
<TextBlock FontSize="36" >
jumped over
<TextBlock.TextDecorations>
<TextDecorationCollection>
<TextDecoration
Ejemplo
En el ejemplo de marcado siguiente se muestra Hyperlink con y sin subrayado:
<!-- Hyperlink with default underline. -->
<Hyperlink NavigateUri="http://www.msn.com">
MSN Home
</Hyperlink>
<Run Text=" | " />
<!-- Hyperlink with no underline. -->
<Hyperlink Name="myHyperlink" TextDecorations="None"
MouseEnter="OnMouseEnter"
MouseLeave="OnMouseLeave"
NavigateUri="http://www.msn.com">
My MSN
</Hyperlink>
En el ejemplo de cdigo siguiente se muestra cmo crear un subrayado para Hyperlink cuando se produce el
evento MouseEnter y quitarlo cuando se produce el evento MouseLeave.
// Display the underline on only the MouseEnter event.
private void OnMouseEnter(object sender, EventArgs e)
{
myHyperlink.TextDecorations = TextDecorations.Underline;
}
// Remove the underline on the MouseLeave event.
private void OnMouseLeave(object sender, EventArgs e)
{
myHyperlink.TextDecorations = null;
}
En el ejemplo de cdigo siguiente se utiliza ScaleTransform para escalar el texto desde su tamao original.
<!-- Scale the text using a ScaleTransform. -->
<TextBlock Name="textblockScaleMaster" FontSize="32" Foreground="SteelBlue"
Text="Scaled Text" Margin="100, 0, 0, 0" Grid.Column="0" Grid.Row="0">
</TextBlock>
<TextBlock FontSize="32" FontWeight="Bold" Foreground="SteelBlue"
Text="{Binding Path=Text, ElementName=textblockScaleMaster}"
Margin="100, 0, 0, 0" Grid.Column="0" Grid.Row="1">
<TextBlock.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.0" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock FontSize="32" FontWeight="Bold" Foreground="SteelBlue"
Text="{Binding Path=Text, ElementName=textblockScaleMaster}"
Margin="100, 0, 0, 0" Grid.Column="0" Grid.Row="2">
<TextBlock.RenderTransform>
<ScaleTransform ScaleX="1.0" ScaleY="1.5" />
</TextBlock.RenderTransform>
</TextBlock>
Nota:
Escalar texto no es lo mismo que aumentar el tamao de la fuente de texto. Los tamaos de fuente se
calculan de forma independiente para proporciona la mejor resolucin en diferentes tamaos. El texto
escalado, por otro lado, conserva las proporciones del texto de tamao original.
En el ejemplo siguiente se muestra el texto sesgado a lo largo del eje X.
Ejemplo de texto sesgado
En el ejemplo de cdigo siguiente se utiliza un objeto SkewTransform para sesgar el texto. Un sesgo, tambin
conocido como distorsin, es una transformacin que expande el espacio de coordenadas de una manera no
uniforme. En este ejemplo, las dos cadenas de texto estn sesgadas -30 y 30 a lo largo de la coordenada x.
<!-- Skew the text using a SkewTransform. -->
<TextBlock Name="textblockSkewMaster" FontSize="32" FontWeight="Bold" Foreground="Maroon"
Text="Skewed Text" Margin="125, 0, 0, 0" Grid.Column="0" Grid.Row="0">
<TextBlock.RenderTransform>
<SkewTransform AngleX="-30" AngleY="0" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock FontSize="32" FontWeight="Bold" Foreground="Maroon"
Text="{Binding Path=Text, ElementName=textblockSkewMaster}"
Margin="100, 0, 0, 0" Grid.Column="0" Grid.Row="1">
En el ejemplo de cdigo siguiente se utiliza un objeto TranslateTransform para desplazar texto. En este
ejemplo, una copia del texto primario ligeramente desplazada crea un efecto de sombra.
<!-- Skew the text using a TranslateTransform. -->
<TextBlock FontSize="32" FontWeight="Bold" Foreground="Black"
Text="{Binding Path=Text, ElementName=textblockTranslateMaster}"
Margin="100, 0, 0, 0" Grid.Column="0" Grid.Row="0">
<TextBlock.RenderTransform>
<TranslateTransform X="2" Y="2" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock Name="textblockTranslateMaster" FontSize="32" FontWeight="Bold"
Foreground="Coral" Text="Translated Text" Margin="100, 0, 0, 0"
Grid.Column="0" Grid.Row="0"/>
Nota:
El objeto DropShadowBitmapEffect proporciona un rico conjunto de caractersticas para ofrecer efectos de
sombra.
En el ejemplo siguiente se utiliza ColorAnimation para animar el color de primer plano del bloque de texto. El
valor del color de primer plano cambia de un color a un segundo color a lo largo de 5 segundos y, a
continuacin, se invierten los valores de color y se contina.
<TextBlock Name="MyChangingColorText" Margin="20" Width="640" Height="100" FontSize="48"
FontWeight="Bold"> This is changing color text
<TextBlock.Foreground>
<SolidColorBrush x:Name="MySolidColorBrush" Color="Maroon" />
</TextBlock.Foreground>
<!-- Animates the text block's color. -->
<TextBlock.Triggers>
<EventTrigger RoutedEvent="TextBlock.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="MySolidColorBrush"
Storyboard.TargetProperty="Color" From="DarkOrange" To="SteelBlue"
Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
En el ejemplo siguiente se utiliza un objeto DoubleAnimation para girar el bloque de texto. El bloque de texto
realiza un giro completo a lo largo de 20 segundos y, a continuacin, contina repitiendo el giro.
<TextBlock Name="MyRotatingText" Margin="20" Width="640" Height="100" FontSize="48"
FontWeight="Bold" Foreground="Teal"> This is rotating text
<TextBlock.RenderTransform>
<RotateTransform x:Name="MyRotateTransform" Angle="0" CenterX="230" CenterY="25"/>
</TextBlock.RenderTransform>
<!-- Animates the text block's rotation. -->
<TextBlock.Triggers>
<EventTrigger RoutedEvent="TextBlock.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyRotateTransform"
Storyboard.TargetProperty="(RotateTransform.Angle)"
From="0.0" To="360" Duration="0:0:10" RepeatBehavior="Forever" />
</Storyboard>
Ejemplo
En el ejemplo de cdigo siguiente, se define un efecto TextEffect para un objeto TextBlock. En este caso, el
efecto de animacin deseado es una transformacin RotateTransform, que se aplicar a cada carcter en la
propiedad Text.
<TextBlock.TextEffects>
<!-- The TextEffect to animate. -->
<TextEffect PositionCount="1" x:Name="MyTextEffect">
<TextEffect.Transform>
<RotateTransform x:Name="TextEffectRotateTransform"
Angle="0" CenterX="10" CenterY="10" />
</TextEffect.Transform>
</TextEffect>
</TextBlock.TextEffects>
Nota:
Si desea girar la cadena de texto completa como una sola unidad, aplique la transformacin
RotateTransform a la propiedad RenderTransform de TextBlock.
En el ejemplo de cdigo siguiente se muestran las animaciones que se definen para las propiedades Angle y
CenterX. La secuencia de animacin se controla definiendo un objeto Int32AnimationUsingKeyFrames y
haciendo referencia a TextEffect al establecer TargetName y TargetProperty. La propiedad PositionStart cambia
de 0 a 12 durante la secuencia de animacin, lo que corresponde a la cadena de texto de 13 caracteres.
<TextBlock.Triggers>
<EventTrigger RoutedEvent="TextBlock.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ParallelTimeline RepeatBehavior="Forever">
<!-- Animates the angle of the RotateTransform applied to the TextEffect. -->
<DoubleAnimation Storyboard.TargetName="TextEffectRotateTransform"
Storyboard.TargetProperty="Angle" From="0" To="360"
Duration="00:00:0.75" BeginTime="0:0:0.25" />
</ParallelTimeline>
<!-- Animates the horizontal center of the RotateTransform applied to the
TextEffect. -->
<DoubleAnimation From="30" To="370" Duration="00:00:13"
RepeatBehavior="Forever" AutoReverse="True"
Storyboard.TargetName="TextEffectRotateTransform"
Storyboard.TargetProperty="CenterX" />
<!-- Animates the position of the TextEffect. -->
<Int32AnimationUsingKeyFrames Storyboard.TargetName="MyTextEffect"
Storyboard.TargetProperty="PositionStart" Duration="0:0:13"
AutoReverse="True" RepeatBehavior="Forever">
<Int32AnimationUsingKeyFrames.KeyFrames>
<DiscreteInt32KeyFrame Value="0" KeyTime="0:0:0" />
Puede controlar el ancho de una sombra estableciendo la propiedad ShadowDepth. Un valor de 4.0 indica un
ancho de la sombra de 4 pxeles. Puede controlar la suavidad, o desenfoque, de una sombra modificando la
propiedad Softness. Un valor de 0.0 indica que no est desenfocada en absoluto; un valor de 1.0 indica el
desenfoque total. En el ejemplo de cdigo siguiente se muestra cmo se crea una sombra suave.
<!-- Soft single shadow. -->
<TextBlock Text="Shadow Text" Foreground="Teal">
<TextBlock.BitmapEffect>
<DropShadowBitmapEffect ShadowDepth="4" Direction="330" Color="Black"
Opacity="0.5" Softness="0.25" />
</TextBlock.BitmapEffect>
</TextBlock>
Nota:
Estos efectos de sombra no atraviesan la canalizacin de representacin de texto de Windows Presentation
Foundation (WPF). Como resultado, ClearType se deshabilita al utilizar estos efectos.
En el ejemplo siguiente se muestra un efecto de sombra paralela ntida aplicada al texto. En este caso, la
sombra no est desenfocada.
Ejemplo de texto con una sombra ntida
Puede crear una sombra ntida estableciendo la propiedad Softness en 0.0, que indica que no se utiliza ningn
desenfoque. Puede controlar la direccin de la sombra modificando la propiedad Direction. Establezca el valor
En el ejemplo de cdigo siguiente se muestra cmo crear y combinar una sombra ntida y suave.
<!-- Hard shadow on top of soft shadow. -->
<TextBlock Text="Shadow Text" Foreground="CornflowerBlue">
<TextBlock.BitmapEffect>
<BitmapEffectGroup>
<BitmapEffectGroup.Children>
<DropShadowBitmapEffect ShadowDepth="5" Direction="330" Color="DarkSlateBlue"
Opacity="0.75" Softness="0.50" />
<DropShadowBitmapEffect ShadowDepth="2" Direction="330" Color="Maroon"
Opacity="0.5" Softness="0.0" />
</BitmapEffectGroup.Children>
</BitmapEffectGroup>
</TextBlock.BitmapEffect>
</TextBlock>
En el ejemplo siguiente se muestra una variacin del ejemplo anterior. En este ejemplo, la sombra suave
muestra una intensidad de color aleatoria. Puede controlar la intensidad de color aleatoria modificando la
propiedad Noise. Un valor de 0.0 indica ningn ruido, un valor de 1.0 indica el ruido mximo.
Ejemplo de texto con una sombra ntida y suave con ruido
En el ejemplo de cdigo siguiente se muestra cmo se crea una sombra con ruido.
<!-- Hard shadow on top of noisy shadow. -->
<TextBlock Text="Shadow Text" Foreground="Silver">
<TextBlock.BitmapEffect>
<BitmapEffectGroup>
<BitmapEffectGroup.Children>
<DropShadowBitmapEffect ShadowDepth="3" Direction="330" Color="Black"
Opacity="0.75" Softness="0.0" />
<DropShadowBitmapEffect Noise="0.5" ShadowDepth="6" Direction="330"
Color="Black" Opacity="0.35" Softness="0.25" />
</BitmapEffectGroup.Children>
Puede controlar el ancho de un resplandor exterior estableciendo la propiedad GlowSize. Un valor de 4.0 indica
un ancho del resplandor exterior de 4 pxeles. En el siguiente ejemplo de cdigo se muestra cmo crear un
efecto de resplandor exterior.
<!-- Shadow effect by creating an outer glow. -->
<TextBlock Text="Shadow Text" Foreground="SteelBlue">
<TextBlock.BitmapEffect>
<OuterGlowBitmapEffect GlowSize="4.0" GlowColor="Orange" Opacity="1.0"/>
</TextBlock.BitmapEffect>
</TextBlock>
Utilizar un efecto de mapa de bits de desenfoque
Un BlurBitmapEffect se puede utilizar para crear un efecto similar a la sombra que se puede colocar detrs de
un objeto de texto. Un efecto de mapa de bits de desenfoque aplicado al texto lo desenfoca de manera
uniforme en todas direcciones.
En el ejemplo siguiente se muestra un efecto de desenfoque aplicado al texto.
Ejemplo de texto con un efecto de desenfoque
En el ejemplo de cdigo siguiente se muestra cmo crear una transformacin para un efecto de sombra.
<!-- Shadow effect by creating a transform. -->
<TextBlock Foreground="Black" Text="Shadow Text" Grid.Column="0" Grid.Row="0">
<TextBlock.RenderTransform>
<TranslateTransform X="3" Y="3" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock Foreground="Coral" Text="Shadow Text" Grid.Column="0" Grid.Row="0">
</TextBlock>
Sin embargo, tambin puede convertir el texto en objetos Geometry, lo que permite crear otros tipos de texto
visualmente enriquecido. Por ejemplo, podra crear un objeto Geometry basado en el contorno de una cadena
de texto.
Ejemplo de un pincel de degradado lineal aplicado a la geometra del contorno de texto
Cuando se convierte el texto en un objeto Geometry, deja de ser una coleccin de caracteres; no se pueden
modificar los caracteres de la cadena de texto. Sin embargo, se puede cambiar la apariencia del texto
convertido modificando sus propiedades de trazo y relleno. El trazo se refiere al contorno del texto convertido;
el relleno se refiere al rea situada dentro del contorno del texto convertido.
En los ejemplos siguientes se muestran varias maneras de crear efectos visuales modificando el trazo y el
relleno del texto convertido.
Ejemplo de cmo establecer el trazo y el relleno en diferentes colores
Tambin es posible modificar el rectngulo de seleccin o resaltado del texto convertido. En el ejemplo
siguiente se muestra una manera de crear efectos visuales modificando el trazo y el resaltado del texto
convertido.
Ejemplo de un pincel de imagen aplicado al trazo y al resaltado
Ejemplo
La clave para convertir texto en un objeto Geometry es utilizar el objeto FormattedText. Una vez creado este
objeto, puede utilizar los mtodos BuildGeometry y BuildHighlightGeometry para convertir el texto en objetos
Geometry. El primer mtodo devuelve la geometra del texto con formato; el segundo mtodo devuelve la
geometra del rectngulo de seleccin del texto con formato. En el ejemplo de cdigo siguiente se muestra
cmo crear un objeto FormattedText y recuperar las geometras del texto con formato y su rectngulo de
seleccin.
/// <summary>
/// Create the outline geometry based on the formatted text.
/// </summary>
public void CreateText()
{
System.Windows.FontStyle fontStyle = FontStyles.Normal;
FontWeight fontWeight = FontWeights.Medium;
if (Bold == true) fontWeight = FontWeights.Bold;
if (Italic == true) fontStyle = FontStyles.Italic;
// Create the formatted text based on the properties set.
Ejemplo
Para dibujar en el fondo de un control, cree un nuevo objeto DrawingBrush y dibuje el texto convertido en el
DrawingContext del objeto. A continuacin, asigne el nuevo DrawingBrush a la propiedad de fondo del control.
Sintaxis
Descripcin
<
<
>
>
&
&
Smbolo de Y comercial.
"
"
Nota:
Si crea un archivo de marcado mediante un editor de texto, como el Bloc de notas de Windows, debe
guardar el archivo en el formato de archivo Unicode UTF-8 para conservar los caracteres especiales
codificados.
En el ejemplo siguiente se muestra cmo se pueden utilizar los caracteres especiales en el texto al crear el
marcado.
Ejemplo
<!-- Display special characters that require special encoding: < > & " -->
<TextBlock>
<
<!-- Less than symbol -->
>
<!-- Greater than symbol -->
&
<!-- Ampersand symbol -->
" <!-- Double quote symbol -->
</TextBlock>
<!-- Display miscellaneous special characters -->
<TextBlock>
Csar
<!-- AE dipthong symbol -->
2006 <!-- Copyright symbol -->
Espaol <!-- Tilde symbol -->
Compatibilidad nativa con perfiles de color avanzados, que incluyen 32 bits por canal (bpc), CMYK,
colores con nombre, tintas n y compatibilidad nativa de transparencia y degradados.
Rendimiento de impresin mejorado tanto para aplicaciones basadas en .NET Framework como en
Win32.
Para los escenarios de impresin bsicos, hay una API simple e intuitiva disponible con un punto nico de
entrada para la interfaz de usuario, la configuracin y el envo de trabajos. Para escenarios avanzados, se
agrega una compatibilidad adicional para la personalizacin de la interfaz de usuario (UI) (o ninguna interfaz de
usuario en absoluto), para la impresin sincrnica o asincrnica y capacidades de impresin por lotes. Ambas
opciones ofrecen compatibilidad de impresin o en modo de confianza total o parcial.
XPS se ha diseado pensando en la extensibilidad. Utilizando el marco de la extensibilidad, es posible agregar
caractersticas y funciones a XPS de una manera modular. Entre las caractersticas de extensibilidad se
incluyen:
Canalizacin de filtros extensible. La canalizacin de filtros del controlador de impresora XPS (XPSDrv)
se ha diseado para permitir la impresin tanto directa como escalable de documentos XPS.
Un grfico vectorial muy complejo, con varias capas o escrito de forma ineficaz puede ser mayor que
una versin de mapa de bits del mismo grfico.
Para la presentacin en pantalla, los archivos XPS incrustan las fuentes de dispositivo, as como las
fuentes con base en el equipo; por el contrario, los archivos de cola de GDI no incrustan las fuentes de
dispositivo. No obstante, ambos tipos de fuentes se agrupan en subconjuntos (vea a continuacin) y
los controladores de impresora pueden quitar las fuentes de dispositivo antes de transmitir el archivo a
la impresora.
Identificacin de recursos comunes. Los recursos que se utilizan varias veces (como una imagen
que representa un logotipo corporativo) se tratan como recursos compartidos y se cargan solamente
una vez.
2.
Utilizar los mtodos Remove y Add del diccionario para quitar la entrada y, a continuacin,
volver a agregarla con el valor deseado.
4.
Utilice el objeto PrintBooleanProperty como valor de la entrada "IsShared" del objeto PrintProperty
Dictionary.
5.
6.
Utilice el objeto PrintStringProperty como valor de la entrada "ShareName" del objeto PrintProperty
Dictionary.
7.
Utilice el segundo objeto PrintStringProperty como valor de la entrada "Location" del objeto
PrintPropertyDictionary.
9.
Cree una matriz de valores de tipo String. Cada elemento es el nombre de un puerto del servidor.
10. Utilice InstallPrintQueue para instalar la nueva impresora con los nuevos valores.
A continuacin se muestra un ejemplo.
LocalPrintServer myLocalPrintServer = new
LocalPrintServer(PrintSystemDesiredAccess.AdministrateServer);
PrintQueue sourcePrintQueue = myLocalPrintServer.DefaultPrintQueue;
PrintPropertyDictionary myPrintProperties = sourcePrintQueue.PropertiesCollection;
// Share the new printer using Remove/Add methods
PrintBooleanProperty shared = new PrintBooleanProperty("IsShared", true);
myPrintProperties.Remove("IsShared");
myPrintProperties.Add("IsShared", shared);
// Give the new printer its share name using SetProperty method
PrintStringProperty theShareName = new PrintStringProperty("ShareName", "\"Son of " +
sourcePrintQueue.Name +"\"");
myPrintProperties.SetProperty("ShareName", theShareName);
// Specify the physical location of the new printer using Remove/Add methods
PrintStringProperty theLocation = new PrintStringProperty("Location", "the supply room");
myPrintProperties.Remove("Location");
myPrintProperties.Add("Location", theLocation);
// Specify the port for the new printer
String[] port = new String[] { "COM1:" };
// Install the new printer on the local print server
PrintQueue clonedPrinter = myLocalPrintServer.InstallPrintQueue("My clone of " +
sourcePrintQueue.Name, "Xerox WCP 35 PS", port, "WinPrint", myPrintProperties);
myLocalPrintServer.Commit();
// Report outcome
Console.WriteLine("{0} in {1} has been installed and shared as {2}", clonedPrinter.Name,
clonedPrinter.Location, clonedPrinter.ShareName);
Console.WriteLine("Press Return to continue ...");
Console.ReadLine();
Identifique el trabajo de impresin que provoca la queja del usuario. Con frecuencia, los usuarios no lo
pueden hacer con precisin. Es posible que no sepan el nombre de los servidores de impresin o de las
impresoras. Puede que describan la ubicacin de la impresora con una terminologa distinta a la
utilizada al establecer su propiedad Location. En consecuencia, es conveniente generar una lista de
trabajos del usuario actualmente enviados. Si hay ms de uno, entonces puede utilizarse la
comunicacin entre el usuario y el administrador del sistema de impresin para determinar con
precisin qu trabajo es el que presenta problemas. Para ello, proceda como sigue.
a.
b.
c.
En cada pasada del bucle de servidor, recorra en bucle todas las colas del servidor para
consultar sus trabajos.
Dentro de cada pasada del bucle de cola, recorra en bucle sus trabajos y recolecte la
informacin identificativa sobre aqullos que ha enviado el usuario que se queja.
2.
Una vez identificado el trabajo de impresin problemtico, examine las propiedades pertinentes para
ver cul puede ser el problema. Por ejemplo, el trabajo se encuentra en un estado de error? o la
impresora correspondiente se ha desconectado antes de imprimir el trabajo?
Puede leer los marcadores de la propiedad JobStatus, que es del tipo PrintJobStatus.
Puede leer cada propiedad pertinente, como IsBlocked y IsInError.
En este ejemplo se muestran ambos mtodos, de modo que previamente se ha preguntado al usuario qu
mtodo desea utilizar y este ha respondido con "Y" (S) si desea utilizar los marcadores de la propiedad
JobStatus. Consulte ms adelante los detalles de los dos mtodos. Por ltimo, la aplicacin utiliza un mtodo
denominado ReportQueueAndJobAvailability para informar de si el trabajo se puede imprimir en este
momento de da.
// When the problematic print job has been identified, enter information about it.
Console.Write("\nEnter the print server hosting the job (including leading slashes \\\\): "
+ "\n(press Return for the current computer \\\\{0}): ", Environment.MachineName);
String pServer = Console.ReadLine();
if (pServer == "")
Lea las propiedades StartTimeOfDay y UntilTimeOfDay del objeto PrintQueue a fin de determinar si la
hora actual se encuentra comprendida entre ellas.
2.
No obstante, las complicaciones surgen del hecho de que estas propiedades no son objetos DateTime. En
cambio, se trata de objetos Int32 que expresan la hora del da como el nmero de minutos transcurridos desde
la medianoche. Es ms, no se trata de la medianoche en la zona horaria actual, sino de la medianoche segn la
hora universal coordinada (UTC).
En el primer ejemplo de cdigo se presenta el mtodo esttico ReportQueueAndJobAvailability, al que se
pasa un objeto PrintSystemJobInfo y que llama a mtodos auxiliares para determinar si el trabajo se puede
imprimir en este momento y, en caso contrario, cundo se puede hacer. Observe que PrintQueue no se pasa al
mtodo. Esto se debe a que PrintSystemJobInfo incluye una referencia a la cola en su propiedad
HostingPrintQueue.
Los mtodos subordinados incluyen el mtodo sobrecargado ReportAvailabilityAtThisTime, que puede
aceptar PrintQueue o PrintSystemJobInfo como parmetro. Tambin est el mtodo TimeConverter.
ConvertToLocalHumanReadableTime. Todos estos mtodos se describen ms adelante.
El mtodo ReportQueueAndJobAvailability comienza comprobando si la cola o el trabajo de impresin no
estn disponibles en este momento. Si cualquiera de ellos no est disponible, comprueba si la cola no est
disponible. Si no est disponible, el mtodo informa de ello y de la hora a la que la cola estar disponible de
nuevo. A continuacin, comprueba el trabajo y, si no est disponible, informa del prximo intervalo de tiempo
en que se podr imprimir. Por ltimo, el mtodo informa del momento ms prximo en que el trabajo se podr
imprimir. Ser el posterior de los dos siguientes.
Al informar sobre las horas del da, se llama al mtodo ToShortTimeString tambin, porque este mtodo
suprime los aos, meses y das del resultado. No se puede restringir la disponibilidad de una cola de impresin
o de un trabajo de impresin a determinados aos, meses o das concretos.
para
extender
la
funcionalidad
de
los
espacios
de
nombres
System.Printing
de
la
coleccin
que
define
el
tipo
de
datos
al
que
pertenece
la
propiedad
PrintCapabilities.PageMediaSizeCapability.
Extender las clases PrintCapabilities y PrintTicket
Aunque las clases PrintTicket y PrintCapabilities no se pueden heredar, puede extender el Print Schema para
reconocer las caractersticas definidas y las nuevas.
Extender la clase PrintTicket
Para utilizar la clase PrintTicket con el sistema extendido de caractersticas, siga los pasos siguientes. A
continuacin se describen algunos detalles.
Si el dispositivo tiene caractersticas nuevas, cree una nueva clase para encapsularlas. (Vea la seccin
Crear una clase NewFeaturesPrintTicket para obtener algunos detalles.)
2.
Si el dispositivo tiene definidas las caractersticas, cree una clase para encapsularlas. (Vea la seccin
Crear una clase DefinedFeaturesPrintTicket para obtener algunos detalles.)
3.
Cree una clase que represente una solicitud de impresin completa. Esta clase representar el papel
en la aplicacin que representara la clase PrintTicket si el dispositivo no tuviese caractersticas
definidas ni nuevas. (Vea la seccin Crear una clase WholePrintTicket para obtener algunos
detalles.)
Si el dispositivo tiene caractersticas nuevas, declare una clase para encapsularlas. Se denominar
NewFeaturesPrintTicket.
2.
Proporcione a la nueva clase las propiedades necesarias para representar las nuevas caractersticas del
dispositivo. Cada propiedad suele pertenecer a uno de los tipos nuevos creados, normalmente una
enumeracin.
3.
Proporcione a la nueva clase una propiedad adicional, que se denominar PrivateNamespace, que
contendr una referencia al espacio de nombres XML privado que define las nuevas caractersticas del
Proporcione a la clase dos constructores. Los constructores se deben basar en los dos constructores de
PrintTicket. Uno no toma parmetros, el otro, un objeto Stream con contenido XML. La secuencia XML
ser un documento de PrintTicket que defina caractersticas nuevas en lugar de comunes. Los
constructores con el parmetro deben producir excepciones basadas en el modelo del constructor de la
clase PrintTicket usada como parmetro en el constructor de la clase.
5.
Cree un mtodo GetXmlStream y un mtodo SaveTo para la clase. Utilice la palabra clave de acceso
"internal" para ambos. Su finalidad es que coincidan con la funcionalidad de los mtodos con igual
nombre definidos en la clase PrintTicket salvo que procesarn los documentos de PrintTicket que
definen las nuevas caractersticas en lugar de las comunes. Estos mtodos se deben asegurar de que
las secuencias generadas tengan una declaracin de espacio de nombres adicional (el valor de la
propiedad PrivateNamespace) en el elemento <PrintTicket > de apertura.
Si el dispositivo tiene definidas caractersticas nuevas, declare una clase para encapsularlas. Se
denominar
DefinedFeaturesPrintTicket.
Se
debe
construir
como
construy
Las propiedades de la clase deben tener nombres que coincidan con el nombre de la
caracterstica correspondiente de la especificacin Print Schema Public Keywords.
Declare una clase que representar una solicitud de impresin completa y, de esta forma, representar
el papel en la aplicacin que habra representado la clase PrintTicket si el dispositivo no tuviese
caractersticas definidas ni nuevas. Se denominar WholePrintTicket.
2.
3.
4.
Proporcione a WholePrintTicket dos constructores. Uno que no tome ningn parmetro y otro que
tome un objeto Stream con contenido XML. El constructor con un parmetro har lo siguiente.
Pasar Stream al constructor del objeto PrintTicket al que hace referencia la propiedad
CommonFeatures. Ese constructor omitir cualquier marcado de Stream que no sea
pertinente para las caractersticas comunes.
5.
Cree GetXmlStream y un mtodo SaveTo para la clase. Su finalidad es coincidir con la funcionalidad
de los mtodos de igual nombre definidos en la clase PrintTicket. Deben tener las caractersticas
siguientes.
Cada uno de estos mtodos debe llamar al mtodo de igual nombre sobre los objetos a los
que hacen referencia las propiedades CommonFeatures, DefinedFeatures (si la hay) y
NewFeatures (si la hay).
Cada mtodo debe concatenar las secuencias generadas por las llamadas descritas en el
punto anterior. Obviamente, todas las etiquetas finales </PrintTicket>, menos la ltima
deben eliminarse; del mismo
las
etiquetas
de
inicio
<PrintTicket > excepto la primera. A menos que no haya caractersticas nuevas, la etiqueta
de apertura debe tener la declaracin de espacio de nombres adicional. (Vea el paso 4b.) Por
este motivo, siempre debera hacer que la secuencia de caractersticas nuevas, si la hubiera,
fuese la primera en la secuencia concatenada ya que siempre tendr la declaracin del nuevo
espacio de nombres en su etiqueta inicial <PrintTicket >.
Cree tres clases nuevas, una para encapsular las nuevas caractersticas (NewFeaturesPrint
Capabilities), otra para encapsular las definidas (DefinedFeaturesPrintCapabilities) y otra para
representar un documento de PrintCapabilities completo (WholePrintCapabilities).
Los tipos de las propiedades de las dos primeras clases nuevas suelen ser ReadOnlyCollection<(Of
<(T>)>). Utilice las propiedades existentes de PrintCapabilities, como CollationCapability, como
modelos.
Siguiendo tambin el modelo de la clase PrintCapabilities existente, los nombres de propiedad deben
tener "Capability" al fin; por ejemplo, BrailleGrade3Capability.
Ninguna de las clases tendr ningn mtodo que no sean los que heredan de la clase Object.
Cada una de las clases tendr un constructor nico que toma un parmetro Stream. Stream ser un
documento de PrintCapabilities.
Los
dos
constructores
DefinedFeaturesPrintCapabilities
NewFeaturesPrintCapabilities
Los
tipos
de
estas
propiedades
sern
PrintCapabilities,
nombres
System.Windows.Xps,
System.Windows.Xps.Packaging
System.Windows.Xps.Serialization
diseados para leer y escribir en documentos de la XPS, incluidos leer y escribir PrintTicket. Vea tambin
PackageRelationship para obtener informacin sobre cmo agregar una relacin a PrintTicket en un paquete.
Se pueden encontrar ejemplos completos de un documento de PrintTicket y un documento de PrintCapabilities
en PrintTicket Example y PrintCapabilities Document Example.
A continuacin, se muestra un ejemplo sencillo de un documento de PrintCapabilities en el que se han pasado
por alto todas las caractersticas del dispositivo menos una. La caracterstica mostrada es DocumentCollate que
es la caracterstica representada por las propiedades PrintCapabilities.CollationCapability y PrintTicket.Collation.
<psf:PrintCapabilities
xmlns:psf="http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1">
<!-- other features omitted -->
<psf:Feature name="psk:DocumentCollate">
<psf:Property name="psf:SelectionType">
<psf:Value xsi:type="xsd:QName">psk:PickOne</psf:Value>
</psf:Property>
<psf:Property name="psk:DisplayName">
<psf:Value xsi:type="xsd:string">Collate Copies</psf:Value>
</psf:Property>
<psf:Option name="psk:Collated" constrained="psk:None">
<psf:Property name="psk:DisplayName">
<psf:Value xsi:type="xsd:string">Yes</psf:Value>
</psf:Property>
</psf:Option>
<psf:Option name="psk:Uncollated" constrained="psk:None">
<psf:Property name="psk:DisplayName">
<psf:Value xsi:type="xsd:string">No</psf:Value>
</psf:Property>
</psf:Option>
</psf:Feature>
<!-- other features omitted -->
</PrintCapabilities>
Observe que se muestra una lista de todas las opciones posibles de la caracterstica (tanto intercaladas como
sin intercalar) y se identifica el estado de cada una (es decir, si se restringe o no). En un documento de
coincidente
exterior
que usa
WholePrintTicket o
WholePrintCapabilities.
Probablemente,
los
mtodos
ms
importantes
que
deber
sobrecargar
son
las
dos
versiones
de
MergeAndValidatePrintTicket. La clase BrailleEmbosser (vea la seccin Derivar una nueva clase mediante
herencia) necesitar reemplazos que usen los parmetros WholePrintTicket y que agreguen la lgica para
validar las solicitudes con nuevas caractersticas en el esquema del espacio de nombres privado. Puede
sobrecargar los mtodos existentes o crear nuevos mtodos denominados MergeAndValidateWholePrint
Ticket.
Dos mtodos que devuelven PrintTicket son ConvertDevModeToPrintTicket y Clone. En .NET Framework hay
otros 15 mtodos, sin contar las sobrecargas, que toman un parmetro PrintTicket y 19 propiedades de tipo
PrintTicket. Probablemente, cualquier aplicacin especificada usar slo unos pocos; por tanto, la carga de
trabajo no ser tan grande como podran sugerir esos nmeros. Afortunadamente, el nico mtodo que
devuelve un objeto PrintCapabilities es GetPrintCapabilities y no existen propiedades con tipo PrintCapabilities.
Expandir las caractersticas definidas por el esquema
Las caractersticas totalmente nuevas no son la nica situacin que podra requerir una extensin de Print
Schema. Adems, es posible que un dispositivo proporcione opciones nuevas y sin definir a una caracterstica
conocida y definida. Puesto que se debe usar un espacio de nombres privado para las nuevas opciones sin
definir de la misma forma que se debe utilizar para una caracterstica totalmente nueva, es probable que sea
ms fcil tratar tales caractersticas extendidas como lo hara con caractersticas totalmente nuevas (pero use
los nombres definidos por el esquema para la caracterstica y los de sus opciones que ya estn definidos):
Cree una instancia del tipo. En el ejemplo siguiente, el tipo es el tipo PrintQueue que se distribuye con
Microsoft .NET Framework, pero un cdigo prcticamente idntico debera funcionar para los tipos que
derive de PrintSystemObject.
2.
3.
Enumere los miembros del diccionario. Para cada uno de ellos, haga lo siguiente.
4.
Convierta el tipo del valor de cada entrada a PrintProperty y utilcelo para crear un objeto
PrintProperty.
5.
// Enumerate the properties, and their types, of a queue without using Reflection
LocalPrintServer localPrintServer = new LocalPrintServer();
PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue();
PrintPropertyDictionary printQueueProperties = defaultPrintQueue.PropertiesCollection;
Console.WriteLine("These are the properties, and their types, of {0}, a {1}",
defaultPrintQueue.Name, defaultPrintQueue.GetType().ToString() +"\n");
foreach (DictionaryEntry entry in printQueueProperties)
{
PrintProperty property = (PrintProperty)entry.Value;
if (property.Value != null)
{
Console.WriteLine(property.Name + "\t(Type: {0})",
property.Value.GetType().ToString());
}
}
Console.WriteLine("\n\nPress Return to continue...");
Console.ReadLine();
2.
3.
4.
El ejemplo siguiente muestra cmo imprimir por lotes todos los archivos XPS de un directorio. Aunque la
aplicacin pide al usuario que especifique el directorio, el mtodo de tres parmetros AddJob(String, String,
Boolean) no requiere una interfaz de usuario (UI). Se puede utilizar en cualquier ruta de acceso de cdigo
donde tenga un nombre de archivo XPS y una ruta de acceso que puede pasarle.
La sobrecarga AddJob(String, String, Boolean) de tres parmetros de AddJob se debe ejecutar en un
subprocesamiento controlado simple cada vez que el parmetro Boolean sea false, que debe ser cuando se
utilice una impresora que no sea XPSDrv. Sin embargo, el estado de subprocesamiento predeterminado para
Microsoft .NET es de varios subprocesos. Esta opcin predeterminada se debe invertir, dado que el ejemplo
asume que se trata de una impresora que no es XPSDrv.
Hay
dos
maneras
de
cambiar
el
valor
predeterminado.
Una
consiste
en
agregar
simplemente
Para simplificar, el ejemplo anterior utiliza la presencia de una extensin *.xps como prueba de que un
archivo es XPS. Sin embargo, los archivos XPS no tienen necesariamente esta extensin. Herramienta isXPS
Conformance es un medio de probar la validez XPS de un archivo.
2.
3.
Dentro de cada paso del bucle de servidor, recorra en bucle todas las colas del servidor y lea cada
propiedad que pueda indicar que la cola no est funcionando actualmente.
Puede leer los marcadores de la propiedad QueueStatus, que es del tipo PrintQueueStatus.
Puede leer cada propiedad pertinente, como IsOutOfPaper y IsPaperJammed.
En este ejemplo se muestran ambos mtodos, de modo que previamente se ha preguntado al usuario qu
mtodo desea utilizar y este ha respondido con "y" (S) si desea utilizar los marcadores de la propiedad
QueueStatus. Consulte ms adelante los detalles de los dos mtodos.
Por ltimo, se presentan los resultados al usuario.
// Survey queue status for every queue on every print server
String line;
String statusReport = "\n\nAny problem states are indicated below:\n\n";
while ((line = fileOfPrintServers.ReadLine()) != null)
{
PrintServer myPS = new PrintServer(line, PrintSystemDesiredAccess.AdministrateServer);
PrintQueueCollection myPrintQueues = myPS.GetPrintQueues();
statusReport = statusReport + "\n" + line;
foreach (PrintQueue pq in myPrintQueues)
{
pq.Refresh();
statusReport = statusReport + "\n\t" + pq.Name + ":";
if (useAttributesResponse == "y")
{
TroubleSpotter.SpotTroubleUsingQueueAttributes(ref statusReport, pq);
// TroubleSpotter class is defined in the complete example.
}
else
{
TroubleSpotter.SpotTroubleUsingProperties(ref statusReport, pq);
}
}// end for each print queue
}// end while list of print servers is not yet exhausted
fileOfPrintServers.Close();
Console.WriteLine(statusReport);
Console.WriteLine("\nPress Return to continue.");
Console.ReadLine();
Para comprobar estado de la impresora mediante los marcadores de la propiedad QueueStatus, se comprueba
cada marcador pertinente para ver si est establecido. La manera estndar de comprobar si un bit est
establecido en un conjunto de indicadores de bits, es realizar la operacin de AND lgico con el conjunto de
marcadores como uno de los operandos y con el propio marcador como el otro operando. Puesto que el
marcador nicamente tiene un bit establecido, el resultado de la operacin de AND lgico es que, a lo sumo,
ese mismo bit est establecido. Para averiguar si lo est o no, basta con comparar el resultado de la operacin
de AND lgico con el propio marcador.
2.
3.
Si la impresora admite la impresin a dos caras, el ejemplo de cdigo crea una PrintTicket, que solicita
la impresin a dos caras. Pero la aplicacin no especifica cada posible configuracin de impresora
disponible en el elemento PrintTicket. Esto malgastara tiempo de programacin y tiempo de ejecucin
del programa. En lugar de ello, en el cdigo se establece nicamente la solicitud de impresin a dos
caras y, a continuacin, se combina PrintTicket con otra PrintTicket totalmente configurada y validada.
En este caso, se utiliza la PrintTicket predeterminada del usuario.
4.
5.
A continuacin, en el ejemplo se comprueba que la nueva PrintTicket solicita la impresin a dos caras.
Si lo hace, entonces se convierte en la nueva solicitud de impresin predeterminada del usuario. Si se
omitiera el paso 2 anterior y la impresora no admite la impresin a dos caras con giro en el lado largo,
entonces el resultado de la prueba sera false. (Consulte la nota anterior.)
6.
mtodo Commit.
/// <summary>
/// Changes the user-default PrintTicket setting of the specified print queue.
/// </summary>
/// <param name="queue">the printer whose user-default PrintTicket setting needs to be
changed</param>
static private void ChangePrintTicketSetting(PrintQueue queue)
{
// Obtain the printer's PrintCapabilities so we can determine whether or not
// duplexing printing is supported by the printer.
PrintCapabilities printcap = queue.GetPrintCapabilities();
// The printer's duplexing capability is returned as a read-only collection of
// duplexing options that can be supported by the printer. If the collection returned
// contains the duplexing option we want to set, it means the duplexing option we want
// to set is supported by the printer,
// so we can make the user-default PrintTicket setting change.
if (printcap.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge))
{
// To change the user-default PrintTicket, we can first create a delta PrintTicket
// with the new duplexing setting.
PrintTicket deltaTicket = new PrintTicket();
deltaTicket.Duplexing = Duplexing.TwoSidedLongEdge;
// Then merge the delta PrintTicket onto the printer's current user-default
// PrintTicket, and validate the merged PrintTicket to get the new PrintTicket we
// want to set as the printer's new user-default PrintTicket.
ValidationResult result = queue.MergeAndValidatePrintTicket(queue.UserPrintTicket,
deltaTicket);
// The duplexing option we want to set could be constrained by other PrintTicket
// settings or device settings. We can check the validated merged PrintTicket to
// see whether the validation process has kept the duplexing option we want to set
// unchanged.
if (result.ValidatedPrintTicket.Duplexing == Duplexing.TwoSidedLongEdge)
{
// Set the printer's user-default PrintTicket and commit the set operation.
queue.UserPrintTicket = result.ValidatedPrintTicket;
queue.Commit();
Console.WriteLine("PrintTicket new duplexing setting is set on '{0}'.",
7. Grficos y Multimedia
Windows Presentation Foundation (WPF) incluye compatibilidad con grficos 2D y 3D, animaciones y multimedia
de gran calidad. Algunas de las caractersticas clave de la plataforma grfica son:
Precisin mejorada. El sistema de coordenadas de WPF utiliza valores de tipo double en lugar de
float. Las transformaciones y los valores de opacidad tambin se expresan usando valores de tipo
double. WPF admite adems una gama de color ms amplia (scRGB) y ofrece compatibilidad integrada
para la administracin de entradas de diferentes espacios de color.
de
escenas,
bucles
de
representacin
interpolaciones
bilineales.
WPF
ofrece
Formas 2D
WPF proporciona una biblioteca de formas 2D de uso comn, dibujadas mediante vectores, tales como
rectngulos y elipses que se muestran en la ilustracin siguiente.
Estas formas intrnsecas de WPF no son solamente formas: son elementos programables que implementan
muchas de las caractersticas que se esperan de la mayora de los controles comunes, incluida la entrada de
teclado y mouse.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Window1" >
<Ellipse Fill="LightBlue" MouseUp="ellipseButton_MouseUp" />
</Window>
public partial class Window1 : Window
{
void ellipseButton_MouseUp(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Me, a simple ellipse, was mouse clicked!");
}
}
La ilustracin siguiente muestra el resultado del marcado XAML y del cdigo subyacente anterior.
Geometras 2D
Cuando las formas 2D que proporciona WPF no sean suficientes, puede utilizar la compatibilidad de WPF con
geometras y trayectorias para crear formas propias. La ilustracin siguiente muestra cmo puede utilizar
geometras para crear formas, como un pincel de dibujo, y para recortar otros elementos de WPF.
Efectos 2D
WPF proporciona una biblioteca de clases 2D que puede utilizar para crear diversos efectos. La capacidad de
representacin 2D de WPF ofrece la capacidad de pintar elementos interfaz de usuario con degradados, mapas
de bits, dibujos y vdeos; tambin de manipularlos utilizando giro, escalado y sesgo. La ilustracin siguiente
proporciona un ejemplo de los muchos efectos que puede lograr utilizando los pinceles de WPF.
Representacin 3D
WPF proporciona un conjunto de capacidades de representacin 3D que se integran con la compatibilidad con
grficos 2D en WPF para crear interesantes diseos, interfaz de usuario y visualizaciones de datos. En un
extremo del espectro, WPF permite representar imgenes 2D en las superficies de formas 3D, que se muestran
en la siguiente ilustracin.
Animacin
Utilice animaciones para hacer que los controles y los elementos crezcan, se agiten, giren y se desvanezcan,
para crear interesantes transiciones de pgina y para otros efectos. Dado que WPF permite animar la mayora
de las propiedades, no solamente podr animar la mayora de los objetos de WPF, sino que tambin puede
utilizar WPF para animar los objetos personalizados que cree.
Multimedia
Las imgenes, el vdeo y el audio son medios multimedia para la difusin de informacin y experiencias de
usuario.
Imgenes
Las imgenes, entre las que se incluyen iconos, fondos e incluso partes de animaciones, son una parte bsica
de la mayora de las aplicaciones. Dado que frecuentemente necesitar utilizar imgenes, WPF expone la
capacidad de trabajar con ellas de diversas maneras. La ilustracin siguiente muestra solamente una de esas
maneras.
Vdeo y audio
Una caracterstica bsica de las capacidades grficas de WPF es la compatibilidad nativa para el trabajo con
multimedia, lo que incluye vdeo y audio. El ejemplo siguiente muestra cmo insertar un reproductor
multimedia en una aplicacin.
<MediaElement Source="media\numbers.wmv" Width="450" Height="250" />
MediaElement es capaz de reproducir tanto vdeo como audio, y es lo suficientemente extensible como para
permitir la creacin fcil de UIs personalizadas.
Clculos del rectngulo de seleccin: determinacin del rectngulo delimitador de un elemento visual.
Control de eventos
Diseo
Estilos
Enlace de datos
Globalizacin
Visual se expone como una clase abstracta pblica de la que se deben derivar las clases secundarias. En la
ilustracin siguiente se muestra la jerarqua de los objetos visuales que se exponen en WPF.
Jerarqua de la clase Visual
Clase DrawingVisual
DrawingVisual es una clase de dibujo ligera que se utiliza para representar formas, imgenes o texto. Esta clase
se considera ligera porque no proporciona administracin del diseo ni control de eventos, lo que mejora su
rendimiento en tiempo de ejecucin. Por esta razn, los dibujos son idneos para fondos e imgenes
prediseadas. DrawingVisual se puede utilizar para crear un objeto visual personalizado.
Clase Viewport3DVisual
Viewport3DVisual proporciona un puente entre los objetos 2D Visual y Visual3D. La clase Visual3D es la clase
base para los elementos visuales 3D. Viewport3DVisual requiere que se defina un valor Camera y un valor
Viewport. La cmara permite ver la escena. El rea de visualizacin establece dnde se asigna la proyeccin a
la superficie 2D.
Clase ContainerVisual
La clase ContainerVisual se utiliza como contenedor de una coleccin de objetos Visual. La clase DrawingVisual
se deriva de la clase ContainerVisual, lo que le permite contener una coleccin de objetos visuales.
Dibujar contenido en objetos visuales
Un objeto Visual almacena sus datos de representacin como una lista de instrucciones de grficos
vectoriales. Cada elemento de la lista de instrucciones representa un conjunto de bajo nivel de datos de los
grficos y de recursos asociados en un formato serializado. Hay cuatro tipos diferentes de datos de
representacin que pueden incluir contenido de dibujo.
Tipo de contenido de
los dibujos
Descripcin
Grficos vectoriales
Imagen
Glifo
Vdeo
DrawingContext permite rellenar un objeto Visual con contenido visual. Cuando se utilizan los comandos de
dibujo de un objeto DrawingContext, en realidad se est almacenando un conjunto de datos de representacin
que el sistema de grficos utilizar ms adelante; no se dibuja en la pantalla en tiempo real.
Los elementos de nodos que no sean de hoja de la jerarqua, tales como ContentPresenter, se utilizan
para contener elementos secundarios, no contienen listas de instrucciones.
Si un elemento visual contiene una lista de instrucciones de grficos vectoriales y elementos visuales
secundarios, la lista de instrucciones del elemento visual primario se representar antes que los
dibujos de cualquiera de los objetos visuales secundarios.
rbol visual
El rbol visual contiene todos los elementos visuales utilizados en la interfaz de usuario de una aplicacin.
Puesto que un elemento visual contiene informacin de dibujo conservada, puede considerar el rbol visual
como una representacin grfica de la escena, que contiene toda la informacin de representacin necesaria
Orden de representacin
El rbol visual determina el orden de representacin de los objetos visuales y de dibujo de WPF. El orden del
recorrido comienza en el elemento visual raz, que es el nodo del nivel superior del rbol visual. A continuacin
se recorren los elementos secundarios del elemento visual raz, de izquierda a derecha. Si un elemento visual
tiene elementos secundarios, stos ltimos se recorren antes que los elementos que estn en el mismo nivel
que el elemento visual. Esto significa que el contenido de un elemento visual secundario se representa delante
del propio contenido del elemento visual.
Diagrama del orden de representacin del rbol visual
El rbol visual y el rbol lgico se sincronizan con el conjunto actual de elementos de aplicacin, con lo que se
refleja cualquier adicin, eliminacin o modificacin de elementos. Sin embargo, los rboles presentan vistas
diferentes de la aplicacin. A diferencia del rbol visual, el rbol lgico no expande el elemento
ContentPresenter de un control. Esto significa que no existe una correspondencia unvoca directa entre un rbol
lgico y un rbol visual para el mismo conjunto de objetos. De hecho, al invocar el mtodo GetChildren del
objeto LogicalTreeHelper y el mtodo GetChildVisualTreeHelper del objeto utilizando el mismo elemento
como parmetro se obtienen resultados diferentes.
Ver el rbol visual con XamlPad
La herramienta XamlPad de WPF proporciona una opcin para ver y explorar el rbol visual que corresponde al
contenido de XAML actualmente definido. Haga clic en el botn Mostrar rbol visual en la barra de mens para
mostrar el rbol visual. A continuacin se ilustra la expansin del contenido de XAML en los nodos del rbol
visual en el panel Visual Tree Explorer de XamlPad:
Panel del explorador de rboles visuales de XamlPad
Observe que cada uno de los controles Label, TextBox y Button muestra una jerarqua de objetos visuales
independiente en el panel del explorador de rboles visuales de XamlPad. Esto se debe a que los controles de
WPF tienen una ControlTemplate que contiene el rbol visual de ese control. Al hacer referencia explcitamente
a un control, se hace referencia implcitamente a su jerarqua visual.
Crear perfiles de rendimiento visual
WPF proporciona un conjunto de herramientas de creacin de perfiles de rendimiento que permiten analizar el
funcionamiento en tiempo de ejecucin de la aplicacin y determinar los tipos de optimizacin del rendimiento
que se pueden aplicar. La herramienta Visual Profiler proporciona una vista grfica y completa de los datos de
rendimiento a travs de una asignacin directa al rbol visual de la aplicacin. En esta captura de pantalla, la
En cambio, WPF utiliza un sistema de modo retenido. Esto significa que los objetos de la aplicacin que tienen
aspecto visual definen un conjunto de datos de dibujo serializados. Una vez definidos los datos de dibujo, el
sistema se hace responsable en lo sucesivo de responder a todas las solicitudes de repeticin del dibujo para
representar los objetos de aplicacin. Incluso en tiempo de ejecucin, se puede modificar o crear los objetos de
aplicacin y, an as, confiar en que el sistema responder a las solicitudes de dibujo. La eficacia de un sistema
de grficos de modo retenido reside en que la aplicacin conserva en todo momento la informacin de dibujo
siempre en un estado serializado, pero deja al sistema la responsabilidad de la representacin. En el diagrama
siguiente se muestra cmo delega la aplicacin en WPF para que responda a las solicitudes de dibujo.
Diagrama de la secuencia de representacin de WPF
En el marcado siguiente se muestran dos elementos Path definidos. El segundo elemento utiliza una
ScaleTransform para cambiar el tamao de las instrucciones de dibujo del primer elemento al 300%. Observe
que las instrucciones de dibujo de los elementos Path no sufren cambio alguno.
<Path Data="M10,100 C 60,0 100,200 150,100 z" Fill="{StaticResource
linearGradientBackground}" Stroke="Black" StrokeThickness="2" />
<Path Data="M10,100 C 60,0 100,200 150,100 z" Fill="{StaticResource
linearGradientBackground}" Stroke="Black" StrokeThickness="2" >
<Path.RenderTransform>
<ScaleTransform ScaleX="3.0" ScaleY="3.0" />
</Path.RenderTransform>
</Path>
Grficos independientes de la resolucin y del dispositivo
Clase VisualTreeHelper
La clase VisualTreeHelper es una clase auxiliar esttica que proporciona funcionalidad de bajo nivel para
programar en el nivel de objetos visuales, lo que resulta til en escenarios muy concretos, como el de la
programacin de controles personalizados de alto rendimiento. En la mayora de los casos, los objetos del
marco de trabajo WPF de nivel superior, tales como Canvas y TextBlock, proporcionan mayor flexibilidad y
facilidad de uso.
7.3. Grficos
Windows Presentation Foundation (WPF) proporciona compatibilidad integrada con multimedia, grficos
vectoriales, animacin y creacin de contenido, lo que facilita a los programadores la creacin de interfaces de
usuario y contenido interesantes.
Nota:
Los efectos de mapa de bits de WPF se representan en modo de software. Cualquier objeto que aplique un
efecto tambin se representar en software. Cuando ms se degrada el rendimiento es al utilizar efectos de
mapa de bits en objetos visuales grandes o al animar las propiedades de un efecto de mapa de bits. Esto no
quiere decir que no haya que utilizar nunca los efectos de mapa de bits, pero s debe extremar las
precauciones y efectuar pruebas exhaustivas para asegurarse de que los usuarios obtengan la experiencia
esperada.
Nota:
Los efectos de mapa de bits de WPF no admiten la ejecucin de confianza parcial. Una aplicacin debe tener
permisos de plena confianza para usar efectos de mapa de bits.
Cmo aplicar un efecto
BitmapEffect es una propiedad de Visual. As pues, aplicar efectos a los objetos visuales, tales como Button,
Image, DrawingVisual o UIElement, es tan sencillo como establecer la propiedad. BitmapEffect se puede
establecer en un solo objeto BitmapEffect, pero tambin se pueden encadenar varios efectos mediante el objeto
BitmapEffectGroup.
En el ejemplo de cdigo siguiente se muestra cmo se aplica BitmapEffect en Lenguaje de marcado de
aplicaciones extensible (XAML).
<Button Width="200">You Can't Read This!
<Button.BitmapEffect>
<!-- <BitmapEffectGroup> would go here if you wanted to apply more
then one effect to the Button. However, in this example only
one effect is being applied so BitmapEffectGroup does not need
to be included. -->
<!-- The larger the Radius, the more blurring. The default range is 20.
In addition, the KernelType is set to a box kernel. A box kernel
creates less disruption (less blur) then the default Gaussian kernel. -->
<BlurBitmapEffect Radius="10" KernelType="Box" />
</Button.BitmapEffect>
</Button>
En el ejemplo de cdigo siguiente se muestra cmo se aplica BitmapEffect mediante cdigo.
Nota:
En todos los ejemplos siguientes se aplica un solo efecto a un objeto. Para aplicar varios efectos, utilice
BitmapEffectGroup.
En el ejemplo siguiente se muestra cmo utilizar OuterGlowBitmapEffect para crear un resplandor azul
alrededor del borde exterior de TextBox.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<TextBox Width="200">
<TextBox.BitmapEffect>
<!-- <BitmapEffectGroup> would go here if you wanted to apply more
then one effect to the TextBox. However, in this example only
one effect is being applied so BitmapEffectGroup does not need
to be included. -->
<!-- The OuterGlow is blue, extends out 30 pixels, has the
maximum noise possible, and is 40% Opaque. -->
<OuterGlowBitmapEffect GlowColor="Blue" GlowSize="30" Noise="1"
Opacity="0.4" />
</TextBox.BitmapEffect>
</TextBox>
</StackPanel>
</Page>
La ilustracin siguiente muestra el efecto de resplandor exterior creado en el ejemplo anterior.
En el ejemplo siguiente se muestra cmo utilizar la clase Style para aplicar OuterGlowBitmapEffect a cualquier
TextBox de la pgina que recibe el foco.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Resources define Styles for the entire page. -->
<Page.Resources>
<!-- This style applies to any TextBox on the page. -->
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<!-- When the TextBox gains focus such as when the cursor appears
in the TextBox, apply the OuterGlowBitmapEffect to the TextBox. -->
<Trigger Property="IsFocused" Value="True">
<Setter Property = "BitmapEffect" >
<Setter.Value>
<!-- The OuterGlow is blue, extends out 30 pixels, has the
maximum noise possible, and is 40% Opaque. -->
<OuterGlowBitmapEffect GlowColor="Blue" GlowSize="30" Noise="1"
Opacity="0.4" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<StackPanel>
<!-- The Style defined above applies to this TextBox which creates
an outer glow around the it. -->
<TextBox Name="textBox1" Width="200" />
</StackPanel>
</Page>
En el ejemplo siguiente se muestra cmo utilizar marcado con cdigo subyacente para aplicar OuterGlowBitmap
Effect a TextBox. El efecto de resplandor aparece cuando TextBox recibe el foco. En este ejemplo se muestra el
marcado.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.OuterGlowExample" >
<StackPanel>
<!-- When this TextBox gains focus, a blue glow surrounds it. -->
<TextBox Width="200" GotFocus="OnFocusCreateGlow"></TextBox>
</StackPanel>
</Page>
En el ejemplo siguiente se muestra el cdigo subyacente que controla el evento para el marcado anterior.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Media.Effects;
namespace SDKSample
{
public partial class OuterGlowExample : Page
{
// Add OuterGlow effect.
void OnFocusCreateGlow(object sender, RoutedEventArgs args)
{
// Get a reference to the TextBox.
TextBox myTextBox = (TextBox)sender;
// Initialize a new OuterGlowBitmapEffect that will be applied
// to the TextBox.
OuterGlowBitmapEffect myGlowEffect = new OuterGlowBitmapEffect();
// Set the size of the glow to 30 pixels.
myGlowEffect.GlowSize = 30;
// Set the color of the glow to blue.
Color myGlowColor = new Color();
myGlowColor.ScA = 1;
myGlowColor.ScB = 1;
myGlowColor.ScG = 0;
myGlowColor.ScR = 0;
myGlowEffect.GlowColor = myGlowColor;
// Set the noise of the effect to the maximum possible (range 0-1).
myGlowEffect.Noise = 1;
En el ejemplo siguiente se muestra cmo animar la propiedad GlowSize de OuterGlowBitmapEffect para hacer
que el resplandor se anime hacia fuera cuando TextBox recibe el foco.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel>
<TextBox Width="200">
<TextBox.BitmapEffect>
<!-- This BitmapEffect is targeted by the animation. -->
<OuterGlowBitmapEffect x:Name="myOuterGlowBitmapEffect"
GlowColor="Blue" GlowSize="0" />
</TextBox.BitmapEffect>
<TextBox.Triggers>
<EventTrigger RoutedEvent="TextBox.GotFocus">
<BeginStoryboard>
<Storyboard>
<!-- Animate the GlowSize from 0 to 40 over half a second. -->
<DoubleAnimation Storyboard.TargetName="myOuterGlowBitmapEffect"
Storyboard.TargetProperty="GlowSize" From="0" To="40" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBox.Triggers>
</TextBox>
</StackPanel>
</Page>
el
ejemplo
siguiente
se
muestra
cmo
animar
las
propiedades
ShadowDepth
Softness
de
System;
System.Windows;
System.Windows.Controls;
System.Windows.Media;
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel>
<Button Margin="50" Width="200" Name="myButton">
Click Me to Animate Drop Shadow!
<Button.RenderTransform>
<ScaleTransform x:Name="MyAnimatedScaleTransform"
ScaleX="1" ScaleY="1" CenterX="100" />
</Button.RenderTransform>
<Button.BitmapEffect>
<BitmapEffectGroup>
<BlurBitmapEffect x:Name="myBlurBitmapEffect" Radius="0" KernelType="Box" />
<DropShadowBitmapEffect x:Name="myDropShadowBitmapEffect" Color="Black"
ShadowDepth="0" />
</BitmapEffectGroup>
</Button.BitmapEffect>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<!-- Animate the ScaleX property to make the button
get larger and smaller in the horizontal axis. -->
<DoubleAnimation
Storyboard.TargetName="MyAnimatedScaleTransform"
Storyboard.TargetProperty="ScaleX"
To="5.0" Duration="0:0:1" AutoReverse="True" />
<!-- Animate the ScaleY property to make the button
get larger and smaller in the vertical axis. -->
<DoubleAnimation Storyboard.TargetName="MyAnimatedScaleTransform"
Storyboard.TargetProperty="ScaleY"
To="5.0" Duration="0:0:1" AutoReverse="True" />
<!-- Animate the blur to make the object appear to
be comming out of the screen. Use a spline key
frame to make the blur animate suddenly at the
very end of the animation. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="myBlurBitmapEffect"
Storyboard.TargetProperty="Radius" AutoReverse="True">
<DoubleAnimationUsingKeyFrames.KeyFrames>
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="30" KeyTime="0:0:1"/>
</DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>
<!-- Animate shadow depth of the effect. -->
<DoubleAnimation Storyboard.TargetName="myDropShadowBitmapEffect"
Storyboard.TargetProperty="ShadowDepth"
From="0" To="50" Duration="0:0:1" AutoReverse="True" />
<!-- Animate shadow softness. As the object gets
farther away, the shadow gets softer. -->
<DoubleAnimation
Storyboard.TargetName="myDropShadowBitmapEffect"
Storyboard.TargetProperty="Softness"
From="0" To="1" Duration="0:0:1"
AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>
Nota: en todos los ejemplos siguientes se aplica un solo efecto a un objeto. Para aplicar varios efectos, puede
utilizar BitmapEffectGroup.
Ejemplo
En el ejemplo siguiente se muestra cmo utilizar un efecto BlurBitmapEffect para crear un control Button
desenfocado.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Button Width="200">You Can't Read This!
<Button.BitmapEffect>
<!-- <BitmapEffectGroup> would go here if you wanted to apply more
then one effect to the Button. However, in this example only
one effect is being applied so BitmapEffectGroup does not need
to be included. -->
<!-- The larger the Radius, the more blurring. The default range is 20.
In addition, the KernelType is set to a box kernel. A box kernel
creates less disruption (less blur) then the default Gaussian kernel. -->
<BlurBitmapEffect Radius="10" KernelType="Box" />
</Button.BitmapEffect>
</Button>
</StackPanel>
</Page>
En la ilustracin siguiente se muestra el efecto creado en el ejemplo anterior.
En el ejemplo siguiente se muestra cmo utilizar Style para aplicar el efecto BlurBitmapEffect a un objeto
Button en la pgina mientras se presiona.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Resources define Styles for the entire page. -->
<Page.Resources>
<!-- This style applies to any Button on the page. -->
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<!-- When the Button is pressed, apply the blur. -->
<Trigger Property="IsPressed" Value="true">
<Setter Property = "BitmapEffect" >
<Setter.Value>
<BlurBitmapEffect Radius="10" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<StackPanel>
<!-- The Style defined above applies to this Button which makes
the Button appear blurred while it is pressed. -->
<Button Width="200" >Blurning down the House!</Button>
</StackPanel>
</Page>
En el ejemplo siguiente se muestra cmo utilizar el cdigo para aplicar un efecto BlurBitmapEffect a un objeto
Button cuando se hace clic en l.
A continuacin se muestra el marcado Lenguaje de marcado de aplicaciones extensible (XAML) del ejemplo.
Nota: en todos los ejemplos siguientes se aplica un solo efecto a un objeto. Para aplicar varios efectos, puede
utilizar BitmapEffectGroup.
Ejemplo
En el ejemplo siguiente se muestra cmo utilizar DropShadowBitmapEffect para crear el aspecto de una sombra
por detrs de un objeto Button.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Button Margin="50" Width="200">DropShadow Under this Button
<Button.BitmapEffect>
<!-- <BitmapEffectGroup> would go here if you wanted to apply more
then one effect to the TextBox. However, in this example only
one effect is being applied so BitmapEffectGroup does not need
to be included. -->
<!-- The DropShadowBitmapEffect has several important properties that
determine characteristics of the drop shadow:
- Color: Specifies the color of the drop shadow (in this example black).
- ShadowDepth: Specifies how far displaced the shadow is from the object
casting the shadow. Default is 20.
- Direction: Specifies in what direction the shadow is cast from the object.
It is an angle between 0 and 360 with 0 starting on the right hand side
and moving counter-clockwise around the object. The value of 320 in this
example casts the shadow on the lower right hand side of the button.
- Noise: Specifies how grainy the drop-shadow is. Range is between 0 and 1.
Default is 0.
- Softness: Specifies how soft the shadow. The range is between 0 and 1 with 1
being the softest. Default is 0.5.
- Opacity: Specifies how transparent the shadow is. The range is between 0
and 1 with 1 being fully opaque and 0 fully transparent (not visible). The
default is 1. -->
<DropShadowBitmapEffect Color="Black" Direction="320" ShadowDepth="25"
Softness="1" Opacity="0.5"/>
</Button.BitmapEffect>
</Button>
</StackPanel>
</Page>
En la ilustracin siguiente se muestra el efecto creado en el ejemplo anterior.
En el ejemplo siguiente se muestra cmo utilizar Style para aplicar el efecto DropShadowBitmapEffect a un
objeto Button en la pgina mientras se presiona.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Resources define Styles for the entire page. -->
<Page.Resources>
<!-- This style applies to any Button on the page. -->
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<!-- When the Button is pressed, apply the drop shadow. -->
<Trigger Property="IsPressed" Value="true">
<Setter Property = "BitmapEffect" >
<Setter.Value>
<DropShadowBitmapEffect Color="Black" Direction="320"
ShadowDepth="25" Softness="1" Opacity="0.5"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<StackPanel>
<!-- The Style defined above applies to this Button which creates
a drop shadow when the button is pressed down. -->
<Button Width="200" >Press Me!</Button>
</StackPanel>
</Page>
En el ejemplo siguiente se muestra cmo utilizar el cdigo para aplicar un efecto DropShadowBitmapEffect a un
objeto Button cuando se hace clic en l.
A continuacin se muestra el marcado Lenguaje de marcado de aplicaciones extensible (XAML) del ejemplo.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.DropShadowExample" >
<StackPanel>
<Button Click="OnClickDropShadowButton" Margin="50" Width="200">
Click to Create Drop Shadow!</Button>
</StackPanel>
</Page>
El ejemplo siguiente es el cdigo que controla el evento para el marcado del ejemplo.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Media.Effects;
namespace SDKSample
{
public partial class DropShadowExample : Page
{
// Add Blur effect.
void OnClickDropShadowButton(object sender, RoutedEventArgs args)
{
// Get a reference to the Button.
Button myButton = (Button)sender;
// Initialize a new DropShadowBitmapEffect that will be applied
// to the Button.
DropShadowBitmapEffect myDropShadowEffect = new DropShadowBitmapEffect();
// Set the color of the shadow to Black.
Color myShadowColor = new Color();
myShadowColor.ScA = 1;
// Note that the alpha value is ignored by Color property. The Opacity
// property is used to control the alpha.
myShadowColor.ScB = 0;
myShadowColor.ScG = 0;
myShadowColor.ScR = 0;
myDropShadowEffect.Color = myShadowColor;
// Set the direction of where the shadow is cast to 320 degrees.
myDropShadowEffect.Direction = 320;
// Set the depth of the shadow being cast.
myDropShadowEffect.ShadowDepth = 25;
// Set the shadow softness to the maximum (range of 0-1).
}
En el ejemplo siguiente se muestra cmo animar las propiedades ShadowDepth y Softness de DropShadow
BitmapEffect para que parezca que el objeto Button se eleva sobre la superficie de la pantalla despus de hace
clic en l.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel>
<Button Margin="50" Width="200" Name="myButton">
Click Me to Animate Drop Shadow!
<Button.BitmapEffect>
<!-- This BitmapEffect is targeted by the animation. -->
<DropShadowBitmapEffect x:Name="myDropShadowBitmapEffect" Color="Black"
ShadowDepth="0" />
</Button.BitmapEffect>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<!-- Animate the movement of the button. -->
<ThicknessAnimation
Storyboard.TargetProperty="Margin" Duration="0:0:0.5"
From="50,50,50,50" To="0,0,50,50" AutoReverse="True" />
<!-- Animate shadow depth of the effect. -->
<DoubleAnimation Storyboard.TargetName="myDropShadowBitmapEffect"
Storyboard.TargetProperty="ShadowDepth"
From="0" To="30" Duration="0:0:0.5" AutoReverse="True" />
<!-- Animate shadow softness of the effect. As
the Button appears to get farther from the shadow,
the shadow gets softer. -->
<DoubleAnimation Storyboard.TargetName="myDropShadowBitmapEffect"
Storyboard.TargetProperty="Softness" From="0" To="1" Duration="0:0:0.5"
AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>
el
ejemplo
siguiente
se
muestra
cmo
animar
las
propiedades
ShadowDepth
Softness
de
DropShadowBitmapEffect para que parezca que el objeto Button se eleva sobre la superficie de la pantalla
despus de hace clic en l.
Ejemplo
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel>
<Button Margin="50" Width="200" Name="myButton">
Click Me to Animate Drop Shadow!
<Button.BitmapEffect>
<!-- This BitmapEffect is targeted by the animation. -->
<DropShadowBitmapEffect x:Name="myDropShadowBitmapEffect" Color="Black"
ShadowDepth="0" />
</Button.BitmapEffect>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<!-- Animate the movement of the button. -->
<ThicknessAnimation Storyboard.TargetProperty="Margin" Duration="0:0:0.5"
From="50,50,50,50" To="0,0,50,50" AutoReverse="True" />
<!-- Animate shadow depth of the effect. -->
<DoubleAnimation Storyboard.TargetName="myDropShadowBitmapEffect"
Storyboard.TargetProperty="ShadowDepth"
From="0" To="30" Duration="0:0:0.5" AutoReverse="True" />
<!-- Animate shadow softness of the effect. As
the Button appears to get farther from the shadow,
the shadow gets softer. -->
Nota: en todos los ejemplos siguientes se aplica un solo efecto a un objeto. Para aplicar varios efectos, puede
utilizar BitmapEffectGroup.
Ejemplo
En el ejemplo siguiente se muestra cmo utilizar un efecto BevelBitmapEffect para crear un bisel dentro de un
control Button.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Button Width="200" Height="80" Margin="50">
Bevelled Button
<Button.BitmapEffect>
<!-- <BitmapEffectGroup> would go here if you wanted to apply more
then one effect to the TextBox. However, in this example only
one effect is being applied so BitmapEffectGroup does not need
to be included. -->
<!-- The BevelBitmapEffect has several important properties that
determine characteristics of the bevel effect:
- BevelWidth: Specifies how wide the bevel is (size of the bevel). In this
example, the bevel is fairly wide at 15 (default is 5).
- EdgeProfile: Specifies the curve of the bevel. The default is "Linear".
- LightAngle: Specifies in what direction the "virtual light" is coming from
that create the shadows of the bevel. It is an angle between 0 and 360 with 0
starting on the right hand side and moving counter-clockwise around the object.
The shadows of the bevel are on the opposite side of where the light is cast.
The value of 320 in this example casts the light on the lower right hand side
of the bevel and shadow on the upper left.
- Relief: Specifies the height of the relief of the bevel. Range is between 0 and 1
with 1 having the most relief (darkest shadows). The default is 0.3.
- Smoothness: Specifies how smooth the shadows are. The range is between 0 and 1
with 1 being the softest. Default is 0.5. -->
<BevelBitmapEffect BevelWidth="15" EdgeProfile="CurvedIn" LightAngle="320"
Relief="0.4" Smoothness="0.4" />
</Button.BitmapEffect>
</Button>
</StackPanel>
</Page>
En la ilustracin siguiente se muestra el efecto creado en el ejemplo anterior.
En el ejemplo siguiente se muestra cmo utilizar un estilo Style para aplicar un efecto BevelBitmapEffect a
cualquiera de los objetos Button de la pgina cuando el puntero del mouse se mueve sobre l. Adems, cuando
En el ejemplo siguiente se muestra cmo animar las propiedades BevelWidth y LightAngle del efecto
BevelBitmapEffect para que, cuando el puntero del mouse se mueva sobre el objeto Button, suba el nivel
interior del bisel y la fuente de iluminacin artificial utilizada para el bisel gire alrededor de Button.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel>
<Button Width="200" Height="80" Margin="50">
MouseOver ME!
<Button.BitmapEffect>
<!-- This BitmapEffect is targeted by the animation. -->
<BevelBitmapEffect x:Name="myBevelBitmapEffect" BevelWidth="0"
EdgeProfile="CurvedIn" />
</Button.BitmapEffect>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<BeginStoryboard>
<Storyboard>
<!-- Animate the BevelWidth from 0 to 15. -->
<DoubleAnimation Storyboard.TargetName="myBevelBitmapEffect"
Storyboard.TargetProperty="BevelWidth"
From="0" To="15" Duration="0:0:0.5" AutoReverse="True" />
<!-- Animate the LightAngle so that the light source and
corresponding bevel shadows move around the button. -->
<DoubleAnimation Storyboard.TargetName="myBevelBitmapEffect"
Storyboard.TargetProperty="LightAngle"
From="360" To="0" Duration="0:0:0.5" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>
Nota: en todos los ejemplos siguientes se aplica un solo efecto a un objeto. Para aplicar varios efectos, puede
utilizar BitmapEffectGroup.
Ejemplo
En el ejemplo siguiente se muestra cmo utilizar un efecto EmbossBitmapEffect para crear una imagen con
relieves.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Image Width="360" Source="/images/WaterLilies.jpg" Margin="10" >
<Image.BitmapEffect>
<!-- <BitmapEffectGroup> would go here if you wanted to apply more
then one effect to the TextBox. However, in this example only
one effect is being applied so BitmapEffectGroup does not need
to be included. -->
<!-- The Relief property determines the amount of relief of the emboss.
The valid range of values is 0-1 with 0 having the least relief and
1 having the most. The default value is 0.44. The LightAngle determines
from what direction the artificial light is cast upon the embossed
object which effects shadowing. The valid range is from 0-360 (degrees)
with 0 specifying the right-hand side of the object and successive values
moving counter-clockwise around the object. -->
<EmbossBitmapEffect Relief="0.8" LightAngle="320" />
</Image.BitmapEffect>
</Image>
</StackPanel>
</Page>
En el ejemplo siguiente se muestra cmo utilizar el objeto Style para aplicar EmbossBitmapEffect a cualquier
Image de la pgina.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Resources define Styles for the entire page. -->
<Page.Resources>
<!-- This style applies to any Image on the page. -->
<Style TargetType="{x:Type Image}">
<Setter Property="BitmapEffect" >
<Setter.Value>
<EmbossBitmapEffect Relief="0.8" />
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<StackPanel>
<!-- The Style defined above applies to this Image which applies
the EmbossBitmapEffect. -->
<Image Width="360" Source="/images/WaterLilies.jpg" Margin="10" />
</StackPanel>
</Page>
En el ejemplo siguiente se muestra cmo utilizar el cdigo para aplicar EmbossBitmapEffect a un objeto Image
cuando se carga.
A continuacin se muestra el marcado Lenguaje de marcado de aplicaciones extensible (XAML) del ejemplo.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.EmbossExample" >
<StackPanel>
<!-- When this image loads, an EmbossBitmapEffect is applied to it. -->
<Image Width="360" Loaded="OnLoadEmbossImage" Source="/images/WaterLilies.jpg" />
</StackPanel>
</Page>
El ejemplo siguiente es el cdigo que controla el evento para el marcado.
using System;
using System.Windows;
DoubleAnimationUsingKeyFrames();
myDoubleAnimationUsingKeyFrames.AutoReverse = true;
// Set the animation to target the Radius property
// of the object named "myBlurBitmapEffect."
Storyboard.SetTargetName(myDoubleAnimationUsingKeyFrames,
"myBlurBitmapEffect");
Storyboard.SetTargetProperty(myDoubleAnimationUsingKeyFrames, new
PropertyPath(BlurBitmapEffect.RadiusProperty));
myDoubleAnimationUsingKeyFrames.KeyFrames.Add(new SplineDoubleKeyFrame(
30, // Target value (KeyValue)
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)), // KeyTime
new KeySpline(0.6, 0.0, 0.9, 0.0) // KeySpline
)
);
// Create a storyboard and add the animations to it.
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimationScaleX);
myStoryboard.Children.Add(myDoubleAnimationScaleY);
myStoryboard.Children.Add(myDoubleAnimationShadowDepth);
myStoryboard.Children.Add(myDoubleAnimationUsingKeyFrames);
// Start the storyboard when button is clicked.
myButton.Click += delegate(object sender, RoutedEventArgs e)
{
myStoryboard.Begin(this);
};
StackPanel myStackPanel = new StackPanel();
myStackPanel.Children.Add(myButton);
this.Content = myStackPanel;
}
}
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel>
<Button Margin="50" Width="200" Name="myButton">
Click Me to Animate Drop Shadow!
<Button.RenderTransform>
<ScaleTransform x:Name="MyAnimatedScaleTransform"
ScaleX="1" ScaleY="1" CenterX="100" />
</Button.RenderTransform>
<Button.BitmapEffect>
<BitmapEffectGroup>
<BlurBitmapEffect x:Name="myBlurBitmapEffect" Radius="0" KernelType="Box" />
<DropShadowBitmapEffect x:Name="myDropShadowBitmapEffect" Color="Black"
ShadowDepth="0" />
</BitmapEffectGroup>
</Button.BitmapEffect>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<!-- Animate the ScaleX property to make the button
get larger and smaller in the horizontal axis. -->
<DoubleAnimation Storyboard.TargetName="MyAnimatedScaleTransform"
Storyboard.TargetProperty="ScaleX"
To="5.0" Duration="0:0:1" AutoReverse="True" />
<!-- Animate the ScaleY property to make the button
get larger and smaller in the vertical axis. -->
<DoubleAnimation Storyboard.TargetName="MyAnimatedScaleTransform"
Storyboard.TargetProperty="ScaleY"
To="5.0" Duration="0:0:1" AutoReverse="True" />
<!-- Animate the blur to make the object appear to
be comming out of the screen. Use a spline key
frame to make the blur animate suddenly at the
very end of the animation. -->
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="myBlurBitmapEffect"
Storyboard.TargetProperty="Radius" AutoReverse="True">
<DoubleAnimationUsingKeyFrames.KeyFrames>
<SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="30"
KeyTime="0:0:1" />
</DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>
<!-- Animate shadow depth of the effect. -->
<DoubleAnimation Storyboard.TargetName="myDropShadowBitmapEffect"
Storyboard.TargetProperty="ShadowDepth"
From="0" To="50" Duration="0:0:1" AutoReverse="True" />
<!-- Animate shadow softness. As the object gets
farther away, the shadow gets softer. -->
<DoubleAnimation Storyboard.TargetName="myDropShadowBitmapEffect"
Storyboard.TargetProperty="Softness"
From="0" To="1" Duration="0:0:1" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
7.3.2. Pinceles
En los temas siguientes se describe cmo utilizar los pinceles de Windows Presentation Foundation (WPF) para
"pintar" contenido en la pantalla
La mayora de los objetos visuales permiten especificar cmo pintarlos. En la tabla siguiente se muestra una
lista de algunos objetos y propiedades comunes con los que puede utilizar un objeto Brush.
Clase
Propiedades de pincel
Border
BorderBrush, Background
Control
Background, Foreground
Panel
Background
Pen
Brush
Shape
Fill, Stroke
TextBlock
Background
En las secciones siguientes se describen los distintos tipos de Brush y se proporciona un ejemplo de cada uno.
Pintar con un color slido
Un objeto SolidColorBrush pinta un rea con un color (Color) slido. Existen varias maneras de especificar la
propiedad Color de SolidColorBrush: por ejemplo, puede especificar sus canales alfa, rojo, azul y verde, o
utilizar uno de los colores predefinidos proporcionados por la clase Colors.
En el ejemplo siguiente se usa un objeto SolidColorBrush para pintar la propiedad Fill de un objeto Rectangle.
En la siguiente ilustracin se muestra el rectngulo pintado.
Rectngulo pintado mediante SolidColorBrush
/>
Para obtener una lista de pinceles predefinidos disponibles, consulte la clase Brushes.
Para obtener una lista de pinceles del sistema disponibles, consulte la clase SystemColors.
Procese el contenido del pincel. Para GradientBrush, esto significa determinar el rea de degradado.
Para TileBrush, se asigna Viewbox a Viewport. sta se convierte en la salida del pincel.
2.
4.
5.
Dado que RelativeTransform se aplica mientras la salida del pincel est asignada a un rectngulo de 1 x 1, el
centro de la transformacin y los valores de desplazamiento parecen ser relativos. Por ejemplo, si utiliz
RotateTransform para girar la salida del pincel 45 grados sobre su centro, se establecer la propiedad CenterX
en 0,5 y la propiedad CenterY en 0,5 para RotateTransform.
En la ilustracin siguiente se muestra la salida de varios pinceles que se han girado 45 grados mediante las
propiedades RelativeTransform y Transform.
En el ejemplo siguiente se utiliza ImageBrush para pintar una rea rectangular con la imagen anterior. Se
aplica RotateTransform a la propiedad RelativeTransform del objeto ImageBrush y se establece su propiedad
Stretch en UniformToFill, lo que debera conservar la relacin de aspecto de la imagen cuando se expanda para
rellenar completamente el rectngulo.
<Rectangle Width="200" Height="100" Stroke="Black" StrokeThickness="1">
<Rectangle.Fill>
<ImageBrush Stretch="UniformToFill">
<ImageBrush.ImageSource>
<BitmapImage UriSource="sampleImages\square.jpg" />
</ImageBrush.ImageSource>
<ImageBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="90" />
</ImageBrush.RelativeTransform>
</ImageBrush>
</Rectangle.Fill>
</Rectangle>
Este ejemplo produce el siguiente resultado.
Observe que la imagen se distorsiona, aunque la propiedad Stretch del pincel se estableci en UniformToFill.
Esto se debe a que la transformacin relativa se aplica despus de asignar la propiedad Viewbox del pincel a su
propiedad Viewport. En la lista siguiente se describen todos los pasos del proceso:
1.
Proyectar el contenido del pincel (Viewbox) sobre su mosaico base (Viewport) utilizando el valor de
Stretch del pincel.
2.
3.
Aplicar RotateTransform.
4.
DrawingBrush: se utiliza para crear mscaras de opacidad complejas a partir de modelos de formas,
imgenes y degradados.
En la ilustracin siguiente se muestra DrawingBrush utilizado como mscara de opacidad.
Ejemplo de mscara de opacidad con DrawingBrush
rr,
gg
bb
representan
valores
hexadecimales
de
dos
dgitos
utilizados
para
especificar,
respectivamente, la cantidad de rojo, verde y azul del color. Cada dgito hexadecimal puede tener un valor
comprendido entre 0 y 9 o entre A y F. 0 es el valor mnimo y F es el mximo. Un valor de alfa de 00 especifica
un color completamente transparente, mientras que un valor de alfa de FF crea un color totalmente opaco. En
el ejemplo siguiente, se utiliza la notacin hexadecimal ARGB para especificar dos colores. El primero es
totalmente opaco, mientras el segundo es completamente transparente.
<Canvas.OpacityMask>
<RadialGradientBrush>
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0" Color="#FF000000"/>
<GradientStop Offset="1" Color="#00000000"/>
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Canvas.OpacityMask>
Utilizar una imagen como mscara de opacidad
Las imgenes tambin se pueden utilizar como mscaras de opacidad. En la ilustracin siguiente se muestra un
ejemplo. Se utiliza un fondo de cuadros para mostrar las partes transparentes de la mscara.
Ejemplo de mscara de opacidad
Para utilizar una imagen como una mscara de opacidad, utilice ImageBrush para contener la imagen. Al crear
una imagen que se va a utilizar como mscara de opacidad, guarde la imagen en un formato que admita varios
niveles de transparencia, como Grficos de red porttiles (PNG). En el ejemplo siguiente se muestra el cdigo
utilizado para crear la ilustracin anterior.
Para utilizar un dibujo como mscara de opacidad, utilice DrawingBrush para contener el dibujo. En el ejemplo
siguiente se muestra el cdigo utilizado para crear la ilustracin anterior:
<!-- With the Opacity Mask-->
<Image Grid.Row="4" Grid.Column="5" Height="150" Width="200"
Source="sampleImages/Waterlilies.jpg">
<Image.OpacityMask>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Brush>
<RadialGradientBrush>
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Black" />
<GradientStop Offset="1" Color="Transparent" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0.05,0.05 0.9,0.9" />
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
Seleccione un pincel de color slido predefinido por nombre. Por ejemplo, puede establecer la
propiedad Background de un botn en "Red" o "MediumBlue". Para obtener una lista del resto de los
pinceles predefinidos de color slido, vea las propiedades estticas de la clase Brushes. A continuacin,
se muestra un ejemplo.
<!-- This button's background is painted with a red SolidColorBrush,
described using a named color. -->
<Button Background="Red">A Button</Button>
Elija un color de la paleta de colores de 32 bits especificando las cantidades de rojo, verde y azul que
se van a combinar en un solo color slido. El formato para especificar un color de la paleta de 32 bits
es "#rrggbb", donde rr es un nmero hexadecimal de dos dgitos que especifica la cantidad relativa de
Use la sintaxis de las etiquetas de las propiedades para describir SolidColorBrush. Esta sintaxis es ms
prolija pero permite especificar valores adicionales, como la opacidad del pincel. En el ejemplo
siguiente, las propiedades Background de dos elementos Button se establecen en rojo totalmente
opaco. El color del primer pincel se describe mediante un nombre de color predefinido y el del
segundo, mediante la notacin hexadecimal.
<!-- Both of these buttons' backgrounds are painted with red
SolidColorBrush objects, described using object element syntax. -->
<Button>A Button
<Button.Background>
<SolidColorBrush Color="Red" />
</Button.Background>
</Button>
<Button>A Button
<Button.Background>
<SolidColorBrush Color="#FFFF0000" />
</Button.Background>
</Button>
Utilice uno de los pinceles predefinidos proporcionados por la clase Brushes. En el ejemplo siguiente,
se establece el valor de la propiedad Background de Button en Red.
Button myButton = new Button();
myButton.Content = "A Button";
myButton.Background = Brushes.Red;
Cree un SolidColorBrush y establezca el valor de su propiedad Color mediante una estructura Color.
Puede utilizar un color predefinido de la clase Colors o puede crear un objeto Color mediante el mtodo
FromArgb esttico.
En el ejemplo siguiente, se muestra cmo establecer la propiedad Color de SolidColorBrush con un
color predefinido.
Button myButton = new Button();
myButton.Content = "A Button";
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Colors.Red;
myButton.Background = mySolidColorBrush;
El objeto FromArgb esttico permite especificar los valores alfa, rojo, verde y azul del color. El intervalo normal
de cada uno de estos valores est comprendido entre 0 y 255. Por ejemplo, un valor alpha de 0 indica que un
color es totalmente transparente, mientras que un valor de 255 indica que el color es totalmente opaco. De
igual forma, un valor rojo de 0 indica que un color no contiene rojo, mientras un valor de 255 indica que un
color contiene la cantidad mxima de rojo posible. En el ejemplo siguiente, el color de un pincel se describe
especificando los valores de alfa, rojo, verde y azul.
Pintar un rea con un degradado
Un pincel de degradado pinta un rea con varios colores que se mezclan entre s a lo largo de un eje. Puede
utilizarlos para crear impresiones de luz y sombras, dando una sensacin tridimensional a los controles.
Tambin puede utilizarlos para simular cristal, cromo, agua y otras superficies suavizadas. WPF proporciona dos
tipos de pinceles de degradado: LinearGradientBrush y RadialGradientBrush.
Degradados lineales
Nota: los ejemplos de degradado de este tema utilizan el sistema de coordenadas predeterminado para
establecer los puntos inicial y final. El sistema de coordenadas predeterminado es relativo a un rectngulo de
seleccin: 0 indica un 0 por ciento del rectngulo de seleccin y 1, un 100 por cien del rectngulo de seleccin.
Puede cambiar este sistema de coordenadas estableciendo la propiedad MappingMode en el valor Absolute. Un
sistema de coordenadas absoluto no es relativo respecto a ningn rectngulo de seleccin. Los valores se
interpretan directamente en el espacio local.
GradientStop es el bloque de creacin bsico de un pincel de degradado. Un punto de degradado especifica una
propiedad Color en una propiedad Offset a lo largo del eje de degradado.
La propiedad Color del punto de degradado especifica el color del punto. Puede establecer el color
mediante un color predefinido (proporcionado por la clase Colors) o especificando los valores ScRGB o
ARGB. En XAML, tambin puede utilizar la notacin hexadecimal para describir un color. Para obtener
ms informacin, vea la estructura Color.
La propiedad Offset del punto de degradado especifica la posicin del color del punto en el eje de
degradado. El desplazamiento es un objeto Double comprendido entre 0 y 1. Cuanto ms se aproxime
el valor de desplazamiento de un punto de degradado a 0, ms prximo estar el color al principio del
degradado. Cuanto ms se aproxime el valor de desplazamiento a 1, ms prximo estar el color al
final del degradado.
El primer punto de degradado especifica el color amarillo en un desplazamiento de 0.0. El segundo punto de
degradado especifica el color rojo en un desplazamiento de 0.25. Los puntos entre estos dos puntos cambian
gradualmente del amarillo al rojo a medida que se mueva de izquierda a derecha por el eje de degradado. El
tercer punto de degradado especifica el color azul en un desplazamiento de 0.75. Los puntos entre los puntos
segundo y tercero de degradado cambian gradualmente del rojo al azul. El cuarto punto de degradado
especifica el color verde oscuro en un desplazamiento de 1.0. Los puntos entre los puntos tercero y cuarto de
degradado cambian gradualmente del azul al verde oscuro.
Eje de degradado
Como se ha mencionado anteriormente, los puntos de degradado de un pincel de degradado lineal se colocan a
lo largo de una lnea, el eje de degradado. Puede cambiar la orientacin y el tamao de la lnea con las
propiedades StartPoint y EndPoint del pincel. Si manipula las propiedades StartPoint y EndPoint del pincel,
puede crear degradados horizontales y verticales, invertir la direccin del degradado, comprimir la extensin
del degradado, etc.
De forma predeterminada, las propiedades StartPoint y EndPoint del pincel de degradado lineal son relativos al
rea que se pinta. El punto (0,0) representa la esquina superior izquierda del rea que se pinta y (1,1), la
esquina inferior derecha. El valor de la propiedad StartPoint predeterminada de LinearGradientBrush es (0,0) y
el de su propiedad EndPoint predeterminada es (1,1). De esta forma, se crea un degradado diagonal que
empieza en la esquina superior izquierda y se extiende hasta la esquina inferior derecha del rea que se pinta.
En la ilustracin siguiente, se muestra el eje de degradado de un pincel de degradado lineal con las propiedades
StartPoint y EndPoint predeterminadas.
En el ejemplo siguiente, se muestra cmo crear un degradado horizontal especificando las propiedades
StartPoint y EndPoint del pincel. Observe que los puntos de degradado son iguales a los de los ejemplos
anteriores; al cambiar las propiedades StartPoint y EndPoint, el degradado se ha cambiado de diagonal a
horizontal.
<!-- This rectangle is painted with a horizontal linear gradient. -->
<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
Degradados radiales
Como un LinearGradientBrush, un RadialGradientBrush pinta un rea con colores que se mezclan juntos a lo
largo de un eje. Los ejemplos anteriores mostraron cmo el eje de un pincel de degradado lineal es una lnea
recta. Un crculo define el eje de un pincel de degradado radial; sus colores "irradian" desde su origen.
En el ejemplo siguiente, se usa un pincel de degradado radial para pintar el interior de un rectngulo.
<!-- This rectangle is painted with a diagonal linear gradient. -->
La propiedad GradientOrigin especifica el punto de inicio del eje de degradado de un pincel de degradado radial.
El eje de degradado irradia desde el origen del degradado hacia el crculo del mismo. Al crculo del degradado
de un pincel lo definen sus propiedades Center, RadiusX y RadiusY.
Las presentaciones de la ilustracin siguientes muestran varios degradados radiales con valores distintos de las
propiedades GradientOrigin, Center, RadiusX y RadiusY.
RadialGradientBrushes con valores distintos de GradientOrigin, Center, RadiusX y RadiusY.
rr,
gg
bb
representan
valores
hexadecimales
de
dos
dgitos
utilizados
para
especificar,
respectivamente, la cantidad de rojo, verde y azul del color. Cada dgito hexadecimal puede tener un valor
comprendido entre 0 y 9 o entre A y F. 0 es el valor mnimo y F, el mximo. Un valor alfa de 00 especifica un
color completamente transparente, mientras que un valor alfa de FF crea un color totalmente opaco. En el
ejemplo siguiente, se utiliza la notacin hexadecimal ARGB para especificar dos colores. El primero es
parcialmente transparente (tiene un valor alfa de x 20), mientras que el segundo es totalmente opaco.
<Rectangle Width="100" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0">
<!-- This gradient stop is partially transparent. -->
<GradientStop Color="#200000FF" Offset="0.0" />
<!-- This gradient stop is fully opaque. -->
<GradientStop Color="#FF0000FF" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
Especificar la opacidad del color en cdigo
Al utilizar cdigo, el mtodo FromArgb esttico permite especificar un valor alfa al crear un color. El mtodo
toma cuatro parmetros de tipo Byte. El primer parmetro especifica el canal alfa del color; los otros tres, los
valores de rojo, verde y azul del color. Cada valor debe estar comprendido entre 0 y 255, ambos inclusive. Un
valor alfa de 0 especifica un color completamente transparente, mientras que un valor alfa de 255, un color
totalmente opaco. En el siguiente ejemplo, se usa el mtodo FromArgb para crear dos colores. El primer color
es parcialmente transparente (tiene un valor alfa de 32), mientras que el segundo es totalmente opaco.
LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush();
// This gradient stop is partially transparent.
myLinearGradientBrush.GradientStops.Add(new GradientStop(Color.FromArgb(32, 0, 0, 255),
0.0));
// This gradient stop is fully opaque.
myLinearGradientBrush.GradientStops.Add(new GradientStop(Color.FromArgb(255, 0, 0, 255),
1.0));
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = myLinearGradientBrush;
O bien, puede utilizar el mtodo FromScRgb, que permite usar los valores de ScRGB para crear un color.
Pintar con imgenes, dibujos, elementos visuales y modelos
Las clases ImageBrush, DrawingBrush y VisualBrush permiten pintar un rea con imgenes, dibujos o
elementos visuales.
De manera predeterminada, ImageBrush expande su imagen a fin de rellenar completamente el rea pintada,
con lo que es posible que se distorsione la imagen si el rea pintada tiene una relacin de aspecto diferente que
la imagen. Puede cambiar este comportamiento modificando el valor predeterminado de la propiedad Stretch,
Fill, por uno de estos valores: None, Uniform o UniformToFill. Dado que ImageBrush es un tipo de TileBrush,
puede especificar con exactitud de qu modo el pincel de imagen rellenar el rea de salida, e incluso crear
tramas.
Ejemplo: Pintar un objeto con una imagen de mapa de bits
En el ejemplo siguiente se usa un objeto ImageBrush para pintar la propiedad Background de un objeto
Canvas.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.BrushExamples.ImageBrushExample"
WindowTitle="ImageBrush Example" Background="White">
<StackPanel>
<Canvas
Height="200" Width="300">
<Canvas.Background>
<ImageBrush ImageSource="sampleImages\Waterlilies.jpg" />
</Canvas.Background>
</Canvas>
</StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Microsoft.Samples.BrushExamples
{
public class ImageBrushExample : Page
{
public ImageBrushExample()
{
Un objeto DrawingBrush pinta un rea con un objeto Drawing. Un objeto de dibujo, o Drawing, describe el
contenido visible, como una forma, un mapa de bits, vdeo o una lnea de texto. Los diferentes tipos de dibujos
describen tipos diferentes de contenido. A continuacin, se muestra una lista de tipos diferentes de objetos de
dibujo.
Al igual que un objeto ImageBrush, un objeto DrawingBrush expande su propiedad Drawing para rellenar su
rea de salida. Puede invalidar este comportamiento cambiando el valor predeterminado (Fill) de la propiedad
Stretch.
Ejemplo: Pintar un objeto con un dibujo
En el ejemplo siguiente se muestra cmo pintar un objeto con un dibujo de tres elipses. GeometryDrawing se
utiliza para describir las elipses.
<Button Content="A Button">
<Button.Background>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="LightBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
Cree un nuevo objeto Visual y utilcelo para establecer la propiedad Visual de VisualBrush.
Utilice un objeto Visual existente, que crea una imagen duplicada del objeto Visual de destino. A
continuacin, puede utilizar VisualBrush para crear efectos interesantes, tales como reflexiones y
ampliaciones.
Cuando se define un nuevo objeto Visual para VisualBrush y ese objeto Visual es un elemento UIElement (por
ejemplo, un panel o un control), el sistema del diseo se ejecuta en el UIElement y sus elementos secundarios
cuando la propiedad AutoLayoutContent est establecida en true. Sin embargo, el UIElement raz queda aislado
esencialmente del resto del sistema: los estilos y el diseo externo no puede penetrar este lmite. Por
consiguiente, debe especificar explcitamente el tamao del elemento UIElement raz, porque su nico elemento
primario es VisualBrush y, por consiguiente, su tamao no se puede ajustar automticamente al rea pintada.
Al igual que ImageBrush y DrawingBrush, un objeto VisualBrush expande su contenido a fin de rellenar su rea
de salida. Puede invalidar este comportamiento cambiando el valor predeterminado (Fill) de la propiedad
Stretch.
Ejemplo: Pintar un objeto con un objeto visual
El rea de salida es el rea que se pinta, como la propiedad Fill de un objeto Ellipse o la propiedad Background
de un objeto Button. En las secciones siguientes se describen los otros dos componentes de TileBrush.
Puede especificar la posicin y las dimensiones del contenido de TileBrush mediante la propiedad Viewbox,
aunque es frecuente dejar la propiedad Viewbox establecida en su valor predeterminado. De manera
predeterminada, Viewbox se configura para contener completamente el contenido del pincel.
Mosaico base
Un objeto TileBrush proyecta su contenido en un mosaico base. La propiedad Stretch controla cmo se expande
el contenido de TileBrush para rellenar el mosaico base. La propiedad Stretch acepta los valores siguientes,
definidos por la enumeracin Stretch:
Uniform: se ajusta la escala del contenido del pincel para que se ajuste completamente dentro del
mosaico. Se conserva la relacin de aspecto del contenido.
UniformToFill: se ajusta la escala del contenido del pincel para que rellene completamente el rea de
salida conservando la relacin de aspecto original del contenido.
En el ejemplo siguiente, se establece el contenido de un objeto ImageBrush de modo que no se expanda para
rellenar el rea de salida.
<Rectangle Width="125" Height="175" Stroke="Black" StrokeThickness="1" Margin="0,0,5,0">
<Rectangle.Fill>
<ImageBrush Stretch="None" ImageSource="sampleImages\testImage.gif"/>
</Rectangle.Fill>
</Rectangle>
// Create a rectangle.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 125;
myRectangle.Height = 175;
myRectangle.Stroke = Brushes.Black;
myRectangle.StrokeThickness = 1;
myRectangle.Margin = new Thickness(0,5,0,0);
// Load the image.
BitmapImage theImage = new BitmapImage(new Uri("sampleImages\\testImage.gif",
UriKind.Relative));
ImageBrush myImageBrush = new ImageBrush(theImage);
// Configure the brush so that it doesn't stretch its image to fill the rectangle.
myImageBrush.Stretch = Stretch.None;
En el ejemplo siguiente, se utiliza una imagen para crear un mosaico con un ancho y un alto del 50%. El
mosaico base se sita en (0,0) en el rea de salida.
<Rectangle Width="50" Height="100">
<Rectangle.Fill>
<!-- Paints an area with 4 tiles. -->
<ImageBrush ImageSource="sampleImages\cherries_larger.jpg" Viewport="0,0,0.5,0.5"
ViewportUnits="RelativeToBoundingBox" TileMode="Tile" />
</Rectangle.Fill>
</Rectangle>
// Create a rectangle.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 50;
myRectangle.Height = 100;
// Load the image.
BitmapImage theImage = new BitmapImage(new Uri("sampleImages\\cherries_larger.jpg",
UriKind.Relative));
ImageBrush myImageBrush = new ImageBrush(theImage);
// Create tiles that are 1/4 the size of the output area.
myImageBrush.Viewport = new Rect(0,0,0.25,0.25);
myImageBrush.ViewportUnits = BrushMappingMode.RelativeToBoundingBox;
// Set the tile mode to Tile.
myImageBrush.TileMode = TileMode.Tile;
// Use the ImageBrush to paint the rectangle's background.
myRectangle.Fill = myImageBrush;
FlipX: igual que Tile, pero volteando en sentido horizontal columnas alternas de mosaicos.
FlipY: igual que Tile, pero volteando en sentido vertical filas alternas de mosaicos.
FlipXY: combinacin de FlipX y FlipY.
En el ejemplo siguiente, se utiliza una imagen para pintar un rectngulo de 100 pxeles de ancho por 100
pxeles de alto. La propiedad Viewport del pincel se ha establecido en 0,0,0.25,0.25; el mosaico base del pincel
ocupa 1/4 del rea de salida. La propiedad TileMode del pincel se establece en FlipXY, para que rellene el
rectngulo con filas de mosaicos.
<Rectangle Width="100" Height="100" >
<Rectangle.Fill>
<ImageBrush ImageSource="sampleImages\triangle.jpg" Viewport="0,0,0.25,0.25"
TileMode="FlipXY" />
</Rectangle.Fill>
</Rectangle>
// Create a rectangle.
Rectangle myRectangle = new Rectangle();
La primera animacin, ColorAnimation, cambia el color del pincel a Gray cuando el mouse entra en el
rectngulo.
La animacin siguiente, ColorAnimation, cambia el color del pincel a Orange cuando el mouse sale del
rectngulo.
La ltima animacin, DoubleAnimation, cambia la opacidad del pincel a 0.0 cuando se presiona el
La primera animacin, DoubleAnimation, anima la propiedad Offset del primer punto de degradado
desde 0.0 hasta 1.0 y de nuevo hasta 0.0. Como resultado, el primer color del degradado cambia del
lado izquierdo al derecho del rectngulo y vuelve al izquierdo.
La segunda animacin, ColorAnimation, anima la propiedad Color del segundo punto de degradado
desde Purple hasta Yellow y de nuevo hasta Purple. Como resultado, el color central del degradado
cambia del prpura al amarillo y vuelve al prpura.
La tercera animacin, ColorAnimation, anima la opacidad de la propiedad Color del tercer punto de
degradado en -1 y vuelve al punto inicial. Como resultado, el tercer color del degradado se desvanece
y, a continuacin, se vuelve de nuevo opaco.
using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.IO;
using System.Collections.ObjectModel;
using System.Windows.Shapes;
namespace SDKSample
{
public partial class ReflectionExample : Page
{
public ReflectionExample()
{
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());
this.Background = Brushes.Black;
StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(50);
Border myReflectedBorder = new Border();
this.RegisterName("ReflectedVisual", myReflectedBorder);
// Create a gradient background for the border.
GradientStop firstStop = new GradientStop();
firstStop.Offset = 0.0;
Color firstStopColor = new Color();
firstStopColor.R = 204;
firstStopColor.G = 204;
firstStopColor.B = 255;
firstStopColor.A = 255;
firstStop.Color = firstStopColor;
GradientStop secondStop = new GradientStop();
secondStop.Offset = 1.0;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace BrushesIntroduction
{
public class TileModeExample : Page
{
public TileModeExample()
{
Background = Brushes.White;
Margin = new Thickness(20);
StackPanel mainPanel = new StackPanel();
mainPanel.HorizontalAlignment = HorizontalAlignment.Left;
// Create a Drawing. This will be the DrawingBrushes' content.
PolyLineSegment triangleLinesSegment = new PolyLineSegment();
triangleLinesSegment.Points.Add(new Point(50, 0));
Estableciendo las propiedades Viewport y TileMode de un objeto DrawingBrush, puede crear una trama
repetitiva. En el ejemplo siguiente se pinta un objeto con una trama creada a partir de un dibujo de dos elipses.
<!-- Demonstrates the use of DrawingBrush. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="White">
<StackPanel Margin="20">
<Rectangle Width="150" Height="150" Stroke="Black" StrokeThickness="1">
<Rectangle.Fill>
<DrawingBrush Viewport="0,0,0.25,0.25" TileMode="Tile">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="10">
<Pen.Brush>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Black" />
<GradientStop Offset="1.0" Color="Gray" />
</LinearGradientBrush>
</Pen.Brush>
</Pen>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Microsoft.Samples.DrawingBrushExamples
{
/// <summary>
/// Paints a Rectangle element with a tiled DrawingBrush.
/// </summary>
public class TiledDrawingBrushExample : Page
{
public TiledDrawingBrushExample()
Para crear un degradado lineal horizontal, cambie las propiedades StartPoint y EndPoint de LinearGradientBrush
a (0,0.5) y (1,0.5). En el ejemplo siguiente, se pinta un objeto Rectangle con un degradado lineal horizontal.
<!-- This rectangle is painted with a horizontal linear gradient. -->
<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
Rectangle horizontalFillRectangle = new Rectangle();
horizontalFillRectangle.Width = 200;
horizontalFillRectangle.Height = 100;
// Create a horizontal linear gradient with four stops.
LinearGradientBrush myHorizontalGradient = new LinearGradientBrush();
myHorizontalGradient.StartPoint = new Point(0,0.5);
myHorizontalGradient.EndPoint = new Point(1,0.5);
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));
// Use the brush to paint the rectangle.
horizontalFillRectangle.Fill = myHorizontalGradient;
En la ilustracin siguiente se muestra el degradado creado en el ejemplo anterior.
Para crear un degradado lineal vertical, cambie las propiedades StartPoint y EndPoint de LinearGradientBrush a
(0.5,0) y (0.5,1). En el ejemplo siguiente, se pinta un objeto Rectangle con un degradado lineal vertical.
<!-- This rectangle is painted with a vertical gradient. -->
<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
Rectangle verticalFillRectangle = new Rectangle();
verticalFillRectangle.Width = 200;
verticalFillRectangle.Height = 100;
// Create a vertical linear gradient with four stops.
LinearGradientBrush myVerticalGradient = new LinearGradientBrush();
myVerticalGradient.StartPoint = new Point(0.5,0);
myVerticalGradient.EndPoint = new Point(0.5,1);
myVerticalGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myVerticalGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25));
myVerticalGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));
myVerticalGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));
// Use the brush to paint the rectangle.
verticalFillRectangle.Fill = myVerticalGradient;
En la ilustracin siguiente se muestra el degradado creado en el ejemplo anterior.
Nota:
Los ejemplos de este tema utilizan el sistema de coordenadas predeterminado para establecer los puntos
inicial y final. El sistema de coordenadas predeterminado es relativo a un rectngulo de seleccin: 0 indica
un 0 por ciento del rectngulo de seleccin y 1, un 100 por cien del mismo. Puede cambiar este sistema de
coordenadas estableciendo la propiedad MappingMode en el valor BrushMappingMode.Absolute. Un sistema
de coordenadas absoluto no es relativo respecto a ningn rectngulo de seleccin. Los valores se
interpretan directamente en el espacio local.
Nota:
En los ejemplos de este tema se utiliza el sistema de coordenadas predeterminado para establecer los
puntos de control. El sistema de coordenadas predeterminado es relativo a un rectngulo de seleccin: 0
indica un 0 por ciento del rectngulo de seleccin y 1, un 100 por cien del mismo. Puede cambiar este
sistema de coordenadas estableciendo la propiedad MappingMode en el valor Absolute. Un sistema de
coordenadas absoluto no es relativo respecto a ningn rectngulo de seleccin. Los valores se interpretan
directamente en el espacio local.
<SystemColor>Brush
Obtiene una referencia esttica a un objeto SolidColorBrush del color del sistema especificado.
<SystemColor>BrushKey
Obtiene una referencia dinmica a un objeto SolidColorBrush del color del sistema especificado.
<SystemColor>Color
Obtiene una referencia esttica a una estructura Color del color del sistema especificado.
<SystemColor>ColorKey
Obtiene una referencia dinmica a la estructura Color del color del sistema especificado.
Un color del sistema es una estructura Color que se puede utilizar para configurar un pincel. Por ejemplo, puede
crear un degradado con los colores del sistema estableciendo las propiedades Color de los puntos de degradado
de un objeto LinearGradientBrush degradado en colores del sistema.
Ejemplo
En el ejemplo siguiente se utiliza una referencia de pincel del sistema dinmica para establecer el fondo de un
botn.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="SystemColors Example" Background="White">
<StackPanel Margin="20">
<!-- Uses a dynamic resource to set the background of a button.
If the desktop brush changes while this application
is running, this button will be updated. -->
<Button Background="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}"
Content="Hello, World!" />
</StackPanel>
</Page>
En el ejemplo siguiente se utiliza una referencia de pincel del sistema esttica para establecer el fondo de un
botn.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
En la ilustracin siguiente se muestra la salida del segundo pincel, cuya propiedad Stretch est establecida en el
valor UniformToFill.
Observe que la propiedad Stretch se comporta exactamente igual para los dems objetos TileBrush, es decir,
para DrawingBrush y VisualBrush.
Asimismo, tenga en cuenta que, aunque parezca que la propiedad Stretch especifica cmo se expandir el
contenido de TileBrush hasta ajustarse a su rea de salida, en realidad especifica cmo se expande el contenido
de TileBrush hasta rellenar su mosaico base.
Ejemplo
En el ejemplo siguiente se alinea el contenido de DrawingBrush, que es un tipo de TileBrush, con la esquina
superior izquierda de su mosaico. Para alinear el contenido, el ejemplo establece la propiedad AlignmentX de
DrawingBrush en Left y la propiedad AlignmentY en Top. Este ejemplo produce el siguiente resultado.
TileBrush con el contenido alineado con la esquina superior izquierda
// Create a TileBrush and align its content to the top-left of its tile.
DrawingBrush topLeftAlignedTileBrush = new DrawingBrush();
topLeftAlignedTileBrush.AlignmentX = AlignmentX.Left;
topLeftAlignedTileBrush.AlignmentY = AlignmentY.Top;
// Set Stretch to None so that the brush's content doesn't automatically expand to
// fill the entire tile.
topLeftAlignedTileBrush.Stretch = Stretch.None;
// Define the brush's content.
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(new EllipseGeometry(new Point(50, 50), 20, 45));
ellipses.Children.Add(new EllipseGeometry(new Point(50, 50), 45, 20));
Pen drawingPen = new Pen(Brushes.Gray, 10);
GeometryDrawing ellipseDrawing = new GeometryDrawing(Brushes.Blue, drawingPen, ellipses);
topLeftAlignedTileBrush.Drawing = ellipseDrawing;
// Use the brush to paint a rectangle.
Rectangle rectangle1 = new Rectangle();
rectangle1.Width = 150;
rectangle1.Height = 150;
rectangle1.Stroke = Brushes.Red;
rectangle1.StrokeThickness = 2;
rectangle1.Margin = new Thickness(20);
rectangle1.Fill = topLeftAlignedTileBrush;
<Rectangle Width="150" Height="150" Stroke="Red" StrokeThickness="2" Margin="20">
<Rectangle.Fill>
<!-- This brush's content is aligned to the top-left of its tile. -->
<DrawingBrush Stretch="None" AlignmentX="Left" AlignmentY="Top">
<DrawingBrush.Drawing>
// Create a TileBrush and align its content to the bottom-right of its tile.
DrawingBrush bottomRightAlignedTileBrush = new DrawingBrush();
bottomRightAlignedTileBrush.AlignmentX = AlignmentX.Right;
bottomRightAlignedTileBrush.AlignmentY = AlignmentY.Bottom;
bottomRightAlignedTileBrush.Stretch = Stretch.None;
// Define the brush's content.
bottomRightAlignedTileBrush.Drawing = ellipseDrawing;
// Use the brush to paint a rectangle.
Rectangle rectangle2 = new Rectangle();
rectangle2.Width = 150;
rectangle2.Height = 150;
rectangle2.Stroke = Brushes.Red;
rectangle2.StrokeThickness = 2;
rectangle2.Margin = new Thickness(20);
rectangle2.Fill = bottomRightAlignedTileBrush;
<Rectangle Width="150" Height="150" Stroke="Red" StrokeThickness="2" Margin="20">
<Rectangle.Fill>
<!-- This brush's content is aligned to the bottom right of its tile. -->
<DrawingBrush Stretch="None" AlignmentX="Right" AlignmentY="Bottom">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Gray" Thickness="10" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
En la ilustracin se resalta el mosaico base para que pueda ver cmo se alinea su contenido. Observe que el
valor AlignmentX no tiene ningn efecto porque el contenido de DrawingBrush rellena horizontalmente todo el
mosaico base.
// Create a TileBrush that generates a tiled pattern and align its
// content to the top-left of its tile.
DrawingBrush tiledTopLeftAlignedTileBrush = new DrawingBrush();
tiledTopLeftAlignedTileBrush.AlignmentX = AlignmentX.Left;
tiledTopLeftAlignedTileBrush.AlignmentY = AlignmentY.Top;
tiledTopLeftAlignedTileBrush.Stretch = Stretch.Uniform;
// Set the brush's Viewport and TileMode to produce a tiled pattern.
tiledTopLeftAlignedTileBrush.Viewport = new Rect(0, 0, 0.25, 0.5);
tiledTopLeftAlignedTileBrush.TileMode = TileMode.Tile;
// Define the brush's content.
tiledTopLeftAlignedTileBrush.Drawing = ellipseDrawing;
// Use the brush to paint a rectangle.
Rectangle rectangle3 = new Rectangle();
rectangle3.Width = 150;
rectangle3.Height = 150;
rectangle3.Stroke = Brushes.Black;
rectangle3.StrokeThickness = 2;
rectangle3.Margin = new Thickness(20);
rectangle3.Fill = tiledTopLeftAlignedTileBrush;
<Rectangle Width="150" Height="150" Stroke="Black" StrokeThickness="2" Margin="20">
<Rectangle.Fill>
<!-- This brush's content is aligned to the top left of its tile. -->
<DrawingBrush Stretch="Uniform" Viewport="0,0,0.25,0.5" TileMode="Tile"
AlignmentX="Left" AlignmentY="Top">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Gray" Thickness="10" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
De nuevo, observe que el valor AlignmentX no tiene ningn efecto porque el contenido de DrawingBrush rellena
horizontalmente todo el mosaico base.
// Create a TileBrush and align its content to the bottom-right of its tile.
DrawingBrush bottomRightAlignedTileBrush = new DrawingBrush();
bottomRightAlignedTileBrush.AlignmentX = AlignmentX.Right;
bottomRightAlignedTileBrush.AlignmentY = AlignmentY.Bottom;
bottomRightAlignedTileBrush.Stretch = Stretch.None;
// Define the brush's content.
bottomRightAlignedTileBrush.Drawing = ellipseDrawing;
// Use the brush to paint a rectangle.
Rectangle rectangle2 = new Rectangle();
rectangle2.Width = 150;
rectangle2.Height = 150;
rectangle2.Stroke = Brushes.Red;
rectangle2.StrokeThickness = 2;
rectangle2.Margin = new Thickness(20);
rectangle2.Fill = bottomRightAlignedTileBrush;
<Rectangle Width="150" Height="150" Stroke="Red" StrokeThickness="2" Margin="20">
<Rectangle.Fill>
<!-- This brush's content is aligned to the bottom right of its tile. -->
<DrawingBrush Stretch="None" AlignmentX="Right" AlignmentY="Bottom">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="MediumBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
<EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="Gray" Thickness="10" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
En el ejemplo se emplean objetos DrawingBrush para demostrar el uso de las propiedades AlignmentX y
AlignmentY. Estas propiedades se comportan de igual forma para todos los pinceles de mosaico: DrawingBrush,
ImageBrush y VisualBrush.
Ejemplo
En el primer ejemplo se aplica un objeto RotateTransform a la propiedad RelativeTransform de un objeto
ImageBrush. Las propiedades CenterX y CenterY de un objeto RotateTransform se establecen ambas en 0,5,
que es la coordenada relativa del punto central de este contenido. Como resultado, el contenido del objeto
ImageBrush gira sobre su centro.
// Create an ImageBrush with a relative transform and use it to paint a rectangle.
ImageBrush relativeTransformImageBrush = new ImageBrush();
relativeTransformImageBrush.ImageSource =
new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative));
// Create a 45 rotate transform about the brush's center
// and apply it to the brush's RelativeTransform property.
RotateTransform aRotateTransform = new RotateTransform();
aRotateTransform.CenterX = 0.5;
aRotateTransform.CenterY = 0.5;
aRotateTransform.Angle = 45;
7.3.3. Dibujos
Los objetos Drawing se utilizan para dibujar eficazmente formas, imgenes o texto. Los dibujos se utilizan al
pintar con un DrawingBrush o programar con objetos Visual.
Los objetos Drawing son verstiles; existen numerosas maneras de utilizar un objeto Drawing.
Puede mostrarlo como una imagen utilizando un objeto DrawingImage y un control Image.
Puede utilizarlo con un objeto DrawingBrush para pintar un objeto, como la propiedad Background de
Page.
WPF proporciona otros tipos de objetos que son capaces de dibujar formas, mapas de bits, texto y multimedia.
Por ejemplo, tambin puede utilizar objetos Shape para dibujar formas, mientras que el control MediaElement
proporciona otra manera de agregar vdeo a la aplicacin. As pues, cundo se deben utilizar los objetos
Drawing? Cuando se pueden sacrificar las caractersticas de nivel de marco de trabajo para obtener ventajas de
rendimiento, o cuando se necesitan las caractersticas de Freezable. Debido a que los objetos Drawing carecen
de compatibilidad con Sistema de diseo, la informacin de entrada y el foco, proporcionan ventajas de
rendimiento que los hace idneos para describir fondos o imgenes prediseadas, as como para dibujos de
bajo nivel con objetos Visual.
Al ser un objeto de tipo Freezable, los objetos Drawing obtienen varias caractersticas especiales, entre las que
se incluyen las siguientes: pueden declararse como recursos, compartirse entre varios objetos, convertirse en
objetos de slo lectura para mejorar el rendimiento, clonarse y convertirse en seguros para subprocesos.
Dibujar una forma
Para dibujar una forma, se utiliza un objeto GeometryDrawing. La propiedad Geometry de un dibujo de
geometra describe la forma que se va a dibujar, su propiedad Brush describe cmo se debe pintar el interior de
la forma, y su propiedad Pen describe cmo se debe dibujar su contorno.
En el ejemplo siguiente se utiliza GeometryDrawing para dibujar una forma. La forma se describe mediante un
objeto GeometryGroup y dos objetos EllipseGeometry. El interior de la forma se pinta con LinearGradientBrush
y su contorno se dibuja con un objeto Pen con la propiedad Black.
En este ejemplo se crea el objeto GeometryDrawing siguiente.
Objeto GeometryDrawing
recurso del proyecto, como se hara con una imagen. En lugar de ello, en el archivo del proyecto debe
establecer en Content el tipo de medios y establecer CopyToOutputDirectory en PreserveNewest o Always.
Para reproducir los elementos multimedia sin crear su propio objeto MediaTimeline, siga estos pasos.
1.
2.
3.
4.
5.
6.
Utilice el mtodo Play de MediaPlayer para iniciar la reproduccin del elemento multimedia.
// Play the video once.
player.Play();
En el ejemplo siguiente se utilizan los objetos VideoDrawing y MediaPlayer para reproducir una vez un archivo
de vdeo.
// Create a VideoDrawing.
MediaPlayer player = new MediaPlayer();
player.Open(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));
VideoDrawing aVideoDrawing = new VideoDrawing();
aVideoDrawing.Rect = new Rect(0, 0, 100, 100);
aVideoDrawing.Player = player;
// Play the video once.
player.Play();
Para controlar mejor el tiempo en los elementos multimedia, utilice un objeto MediaTimeline con los objetos
MediaPlayer y VideoDrawing. MediaTimeline permite especificar si el vdeo se debe repetir. Para utilizar
MediaTimeline con VideoDrawing, siga estos pasos:
1.
2.
3.
4.
En el ejemplo siguiente se utiliza MediaTimeline con MediaPlayer y con VideoDrawing para reproducir
repetidamente un vdeo.
// Create a VideoDrawing that repeats. Create a MediaTimeline.
MediaTimeline mTimeline =
new MediaTimeline(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));
// Set the timeline to repeat.
mTimeline.RepeatBehavior = RepeatBehavior.Forever;
// Create a clock from the MediaTimeline.
MediaClock mClock = mTimeline.CreateClock();
MediaPlayer repeatingVideoDrawingPlayer = new MediaPlayer();
repeatingVideoDrawingPlayer.Clock = mClock;
En la tabla siguiente se describen las propiedades que puede utilizar para manipular el contenido de un objeto
DrawingGroup.
Propiedad
Descripcin
OpacityMask
Ilustracin
Opacity
BitmapEffect
ClipGeometry
GuidelineSet
Transform
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SDKSample
{
public class DrawingImageExample : Page
{
public DrawingImageExample()
{
// Create the Geometry to draw.
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(new EllipseGeometry(new Point(50,50), 45, 20));
ellipses.Children.Add(new EllipseGeometry(new Point(50, 50), 20, 45));
// Create a GeometryDrawing.
GeometryDrawing aGeometryDrawing = new GeometryDrawing();
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SDKSample
{
public class DrawingBrushExample : Page
{
public DrawingBrushExample()
{
// Create the Geometry to draw.
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(new EllipseGeometry(new Point(50,50), 45, 20));
ellipses.Children.Add(new EllipseGeometry(new Point(50, 50), 20, 45));
// Create a GeometryDrawing.
GeometryDrawing aGeometryDrawing = new GeometryDrawing();
aGeometryDrawing.Geometry = ellipses;
// Paint the drawing with a gradient.
aGeometryDrawing.Brush = new LinearGradientBrush(Colors.Blue,
Color.FromRgb(204,204,255), new Point(0,0), new Point(1,1));
// Outline the drawing with a solid color.
aGeometryDrawing.Pen = new Pen(Brushes.Black, 10);
DrawingBrush patternBrush = new DrawingBrush(aGeometryDrawing);
patternBrush.Viewport = new Rect(0, 0, 0.25, 0.25);
patternBrush.TileMode = TileMode.Tile;
patternBrush.Freeze();
// Create an object to paint.
Rectangle paintedRectangle = new Rectangle();
paintedRectangle.Width = 100;
paintedRectangle.Height = 100;
paintedRectangle.Fill = patternBrush;
// Place the image inside a border and add it to the page.
Border exampleBorder = new Border();
exampleBorder.Child = paintedRectangle;
exampleBorder.BorderBrush = Brushes.Gray;
exampleBorder.BorderThickness = new Thickness(1);
exampleBorder.HorizontalAlignment = HorizontalAlignment.Left;
exampleBorder.VerticalAlignment = VerticalAlignment.Top;
exampleBorder.Margin = new Thickness(10);
this.Margin = new Thickness(20);
this.Background = Brushes.White;
this.Content = exampleBorder;
Nota:
Los efectos de mapa de bits de Windows Presentation Foundation (WPF) se representan mediante software.
Cualquier objeto que aplique un objeto BitmapEffecttambin se representar en el software. Evite utilizar
objetos BitmapEffect en presentaciones visuales o animaciones grandes porque este escenario puede
provocar una disminucin del rendimiento del sistema.
Ejemplo
En el ejemplo siguiente se utiliza DrawingGroup para aplicar BlurBitmapEffect a varios objetos Geometry
Drawing.
En la siguiente ilustracin se muestra el resultado de este ejemplo.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Effects;
namespace SDKSample
{
/// <summary>
/// This example creates two DrawingGroup objects,
/// one with a bitmap effect and one without.
/// </summary>
public class BitmapEffectExample : Page
{
public BitmapEffectExample()
{
// Create a DrawingGroup that has no BitmapEffect
PathFigure pLineFigure = new PathFigure();
pLineFigure.StartPoint = new Point(25, 25);
PolyLineSegment pLineSegment = new PolyLineSegment();
pLineSegment.Points.Add(new Point(0,50));
pLineSegment.Points.Add(new Point(25, 75));
pLineSegment.Points.Add(new Point(50, 50));
pLineSegment.Points.Add(new Point(25, 25));
pLineSegment.Points.Add(new Point(25, 0));
pLineFigure.Segments.Add(pLineSegment);
PathGeometry pGeometry = new PathGeometry();
pGeometry.Figures.Add(pLineFigure);
GeometryDrawing drawing1 = new GeometryDrawing(Brushes.Lime,
new Pen(Brushes.Black, 10), pGeometry);
GeometryDrawing drawing2 = new GeometryDrawing(Brushes.Lime,
new Pen(Brushes.Black, 2),new EllipseGeometry(new Point(10,10), 5, 5));
// Create a DrawingGroup
DrawingGroup drawingGroupWithoutBitmapEffect = new DrawingGroup();
drawingGroupWithoutBitmapEffect.Children.Add(drawing1);
drawingGroupWithoutBitmapEffect.Children.Add(drawing2);
// Use an Image control and a DrawingImage to display the drawing.
DrawingImage drawingImage01=new DrawingImage(drawingGroupWithoutBitmapEffect);
// Freeze the DrawingImage for performance benefits.
drawingImage01.Freeze();
Image image01 = new Image();
image01.Source = drawingImage01;
image01.Stretch = Stretch.None;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SDKSample
{
/// <summary>
Ejemplo
El ejemplo siguiente usa RadialGradientBrush como mscara de opacidad para DrawingGroup.
Nota:
Aunque en este ejemplo se usa RadialGradientBrush como mscara de opacidad, tambin son buenos
candidatos los objetos LinearGradientBrush, DrawingBrush, ImageBrush y VisualBrush.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SDKSample
{
/// <summary>
/// Shows how to create and apply an OpacityMask to a DrawinGroup.
/// </summary>
public class OpacityMaskExample : Page
{
public OpacityMaskExample()
{
// Create a GeometryDrawing. Define the drawing's contents.
PathFigure pLineFigure = new PathFigure();
pLineFigure.StartPoint = new Point(25, 25);
PolyLineSegment pLineSegment = new PolyLineSegment();
pLineSegment.Points.Add(new Point(0, 50));
pLineSegment.Points.Add(new Point(25, 75));
pLineSegment.Points.Add(new Point(50, 50));
pLineSegment.Points.Add(new Point(25, 25));
pLineSegment.Points.Add(new Point(25, 0));
pLineFigure.Segments.Add(pLineSegment);
PathGeometry pGeometry = new PathGeometry();
pGeometry.Figures.Add(pLineFigure);
GeometryDrawing drawing1 = new GeometryDrawing(Brushes.Lime,
new Pen(Brushes.Black, 10), pGeometry);
// Create another GeometryDrawing.
GeometryDrawing drawing2 = new GeometryDrawing(Brushes.Lime,
new Pen(Brushes.Black, 2), new EllipseGeometry(new Point(10, 10), 5, 5));
// Create the DrawingGroup and add the geometry drawings.
DrawingGroup aDrawingGroup = new DrawingGroup();
aDrawingGroup.Children.Add(drawing1);
aDrawingGroup.Children.Add(drawing2);
// Define an opacity mask and apply it to the drawing group.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SDKSample
{
public class TransformExample : Page
{
public TransformExample()
{
// Create a GeometryDrawing. Define the drawing's contents.
PathFigure pLineFigure = new PathFigure();
pLineFigure.StartPoint = new Point(25, 25);
PolyLineSegment pLineSegment = new PolyLineSegment();
pLineSegment.Points.Add(new Point(0, 50));
pLineSegment.Points.Add(new Point(25, 75));
pLineSegment.Points.Add(new Point(50, 50));
pLineSegment.Points.Add(new Point(25, 25));
pLineSegment.Points.Add(new Point(25, 0));
pLineFigure.Segments.Add(pLineSegment);
PathGeometry pGeometry = new PathGeometry();
pGeometry.Figures.Add(pLineFigure);
GeometryDrawing drawing1 = new GeometryDrawing(Brushes.Lime,
En el ejemplo siguiente se utiliza DrawingGroup para aplicar una propiedad ClipGeometry a varios objetos
GeometryDrawing.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOption="http://schemas.microsoft.com/winfx/2006/xaml/presentation/option"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions" Background="White" Margin="20">
<Border BorderBrush="Gray" BorderThickness="1" HorizontalAlignment="Left"
VerticalAlignment="Top" Margin="20">
<Image Stretch="None" HorizontalAlignment="Left">
<Image.Source>
<DrawingImage PresentationOptions:Freeze="True">
<DrawingImage.Drawing>
<!-- A DrawingGeometry with an elliptical clip region. -->
<DrawingGroup>
<GeometryDrawing Brush="Pink">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,50,85" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="Lime" Geometry="M 25,25 L 0,50 25,75 50,50 25,25 25,0">
<GeometryDrawing.Pen>
<Pen Thickness="10" Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>
<GeometryDrawing Brush="Lime">
<GeometryDrawing.Geometry>
<EllipseGeometry Center="10,10" RadiusX="5" RadiusY="5" />
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="2" Brush="Black" />
</GeometryDrawing.Pen>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SDKSample
{
public class OpacityExample : Page
{
public OpacityExample()
{
// Create a GeometryDrawing. Define the drawing's contents.
PathFigure pLineFigure = new PathFigure();
pLineFigure.StartPoint = new Point(25, 25);
PolyLineSegment pLineSegment = new PolyLineSegment();
pLineSegment.Points.Add(new Point(0, 50));
pLineSegment.Points.Add(new Point(25, 75));
pLineSegment.Points.Add(new Point(50, 50));
pLineSegment.Points.Add(new Point(25, 25));
pLineSegment.Points.Add(new Point(25, 0));
objeto
GeometryGroup
dos
objetos
EllipseGeometry.
El
interior
de
la
forma
se
pinta
con
LinearGradientBrush y su contorno se dibuja con un objeto Pen con la propiedad Black. GeometryDrawing se
muestra utilizando ImageDrawing y un elemento Image.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SDKSample
{
public class GeometryDrawingExample : Page
{
public GeometryDrawingExample()
{
Para crear complejos ms dibujos, puede combinar varios objetos de dibujo en un mismo dibujo compuesto
utilizando un DrawingGroup.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
namespace SDKSample
{
public class ImageDrawingExample : Page
{
public ImageDrawingExample()
{
// Create a DrawingGroup to combine the ImageDrawing objects.
DrawingGroup imageDrawings = new DrawingGroup();
// Create a 100 by 100 image with an upper-left point of (75,75).
ImageDrawing bigKiwi = new ImageDrawing();
bigKiwi.Rect = new Rect(75, 75, 100, 100);
bigKiwi.ImageSource = new BitmapImage(new Uri(@"sampleImages\kiwi.png",
UriKind.Relative));
imageDrawings.Children.Add(bigKiwi);
// Create a 25 by 25 image with an upper-left point of (0,150).
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SDKSample
{
public class DrawingImageExample : Page
{
public DrawingImageExample()
{
// Create the Geometry to draw.
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(new EllipseGeometry(new Point(50,50), 45, 20));
ellipses.Children.Add(new EllipseGeometry(new Point(50, 50), 20, 45));
// Create a GeometryDrawing.
GeometryDrawing aGeometryDrawing = new GeometryDrawing();
aGeometryDrawing.Geometry = ellipses;
// Paint the drawing with a gradient.
aGeometryDrawing.Brush = new LinearGradientBrush(Colors.Blue,
Color.FromRgb(204,204,255), new Point(0,0), new Point(1,1));
// Outline the drawing with a solid color.
aGeometryDrawing.Pen = new Pen(Brushes.Black, 10);
// Use a DrawingImage and an Image control to display the drawing.
DrawingImage geometryImage = new DrawingImage(aGeometryDrawing);
// Freeze the DrawingImage for performance benefits.
geometryImage.Freeze();
Image anImage = new Image();
anImage.Source = geometryImage;
anImage.HorizontalAlignment = HorizontalAlignment.Left;
// Place the image inside a border and add it to the page.
Border exampleBorder = new Border();
exampleBorder.Child = anImage;
exampleBorder.BorderBrush = Brushes.Gray;
exampleBorder.BorderThickness = new Thickness(1);
exampleBorder.HorizontalAlignment = HorizontalAlignment.Left;
exampleBorder.VerticalAlignment = VerticalAlignment.Top;
exampleBorder.Margin = new Thickness(10);
this.Margin = new Thickness(20);
this.Background = Brushes.White;
this.Content = exampleBorder;
}
}
}
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOption="http://schemas.microsoft.com/winfx/2006/xaml/presentation/option"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions" Background="White" Margin="20">
<Border BorderBrush="Gray" BorderThickness="1" HorizontalAlignment="Left"
7.3.4. Geometras
Geometry es una clase verstil, que se utiliza para representar grficos 2D, realizar pruebas de acceso de
objetos y definir zonas de recorte.
Como puede verse en los ejemplos anteriores, los dos minilenguajes son muy similares. Siempre es posible de
utilizar
un
elemento
PathGeometry
en
cualquier
situacin
en
que
se
pueda utilizar
un
elemento
StreamGeometry; as pues, cul de ellos se debe utilizar? Utilice StreamGeometry cuando no necesite
Descripcin
fillRule
System.Windows.Media.FillRule
Especifica si StreamGeometry utiliza el valor EvenOdd o Nonzero para la propiedad
FillRule.
moveCommand
drawCommands
closeCommand
Comando de movimiento
Especifica el punto de inicio de una nueva figura.
Sintaxis
MMstartPoint O bien mmstartPoint
Trmino
Descripcin
startPoint
System.Windows.Point
El punto de inicio de una nueva figura.
Descripcin
endPoint
System.Windows.Point
El punto final de la lnea.
Descripcin
System.Double
Coordenada x del punto final de la lnea.
Descripcin
System.Double
Coordenada Y del punto final de la lnea.
Sintaxis
C controlPoint1 controlPoint2 endPoint O bien c controlPoint1 controlPoint2 endPoint
Trmino
Descripcin
controlPoint1
System.Windows.Point
El primer punto de control de la curva, que determina la tangente inicial de la curva.
controlPoint2
System.Windows.Point
El segundo punto de control de la curva, que determina la tangente final de la curva.
endPoint
System.Windows.Point
Punto en el que se dibuja la curva.
Descripcin
controlPoint
System.Windows.Point
El primer punto de control de la curva, que determina las tangentes inicial y final de la
curva.
endPoint
System.Windows.Point
Punto en el que se dibuja la curva.
Descripcin
controlPoint2
System.Windows.Point
El punto de control de la curva, que determina la tangente final de la curva.
endPoint
System.Windows.Point
Punto en el que se dibuja la curva.
Descripcin
controlPoint
System.Windows.Point
El punto de control de la curva, que determina el inicio y la tangente de la curva.
endPoint
System.Windows.Point
Punto en el que se dibuja la curva.
Descripcin
size
System.Windows.Size
Radio de X e Y del arco.
rotationAngle
System.Double
Rotacin de la elipse, en grados.
isLargeArcFlag
Establezca este valor en 1 si el ngulo del arco debe ser de 180 grados o mayor; de
lo contrario, establzcalo en 0.
sweepDirectionFlag
endPoint
System.Windows.Point
Punto en el que se dibuja el arco.
Comando de cierre
Finaliza la figura actual y crea una lnea que conecta el punto actual al punto inicial de la figura. Este comando
crea una unin de lnea (esquina) entre el ltimo segmento y el primer segmento de la figura.
Sintaxis
Z O bien Z
Sintaxis de puntos
Describe las coordenadas X e Y de un punto.
Sintaxis
x,y O bien x y
Trmino
Descripcin
System.Double
Coordenada X del punto.
System.Double
Coordenada Y del punto.
Valores especiales
En lugar de un valor numrico estndar, puede utilizar tambin los valores especiales siguientes. Estos valores
distinguen maysculas de minsculas.
clase
Geometry
las
clases
que
derivan
de
ella,
como
EllipseGeometry,
PathGeometry
CombinedGeometry, permiten describir la geometra de una forma 2D. Estas descripciones geomtricas tienen
muchos usos, tales como la definicin de una forma para pintarla en la pantalla o la definicin de pruebas de
posicionamiento y de zonas de recorte. Incluso puede utilizar una geometra para definir un trazado de
animacin.
Los objetos Geometry pueden ser simples, tales como rectngulos y crculos, o bien compuestos, creados a
partir de dos o ms objetos de geometra. Se pueden crear geometras ms complejas utilizando las clases
PathGeometry y StreamGeometry, que permiten describir arcos y curvas.
Dado que Geometry es un tipo de Freezable, los objetos Geometry proporcionan varias caractersticas
especiales: pueden declararse como recursos, compartirse entre varios objetos, convertirse en objetos de slo
lectura para mejorar el rendimiento, clonarse y convertirse en seguros para subprocesos.
Comparacin entre geometras y formas
Las clases Geometry y Shape parecen similares porque ambas describen formas 2D (compare EllipseGeometry
y Ellipse, por ejemplo), pero hay diferencias importantes.
En primer lugar, la clase Geometry hereda de la clase Freezable, mientras que la clase Shape hereda de
FrameworkElement. Dado que son elementos, los objetos Shape se pueden representar y participar en el
sistema del diseo, mientras que los objetos Geometry no pueden.
Aunque los objetos Shape se pueden utilizar de un modo ms directo que los objetos Geometry, los objetos
Geometry son ms verstiles. Aunque un objeto Shape se utiliza para representar grficos 2D, un objeto
Geometry se puede utilizar para definir el rea geomtrica para grficos 2D, definir una zona de recorte o
definir un rea para pruebas de posicionamiento, por ejemplo.
Forma del trazado
Una forma (Shape), la clase Path, en realidad utiliza una geometra (Geometry) para describir su contenido.
Estableciendo la propiedad Data de Path con Geometry y estableciendo sus propiedades Fill y Stroke, puede
representar Geometry.
Propiedades comunes que aceptan un objeto de geometra
En las secciones anteriores se ha mencionado que los objetos de geometra se pueden utilizar con otros objetos
para diversos propsitos, tales como dibujar formas, realizar animaciones o recortar. En la tabla siguiente se
muestra una lista con varias clases que tienen propiedades que aceptan un objeto Geometry.
Tipo
Propiedad
DoubleAnimationUsingPath
PathGeometry
DrawingGroup
ClipGeometry
GeometryDrawing
Geometry
Path
Data
UIElement
Clip
Una RectangleGeometry se define con una estructura Rect que especifica su posicin relativa, as como
su alto y ancho. Puede crear un rectngulo redondeado estableciendo las propiedades RadiusX y
RadiusY.
Una EllipseGeometry se define mediante un punto central, un radio X y un radio Y. En los ejemplos
siguientes se muestra cmo crear geometras simples con fines de representacin y recorte.
Estas mismas formas, as como otras ms complejas, se pueden crear utilizando una PathGeometry o
combinando objetos de geometra entre s, pero estas clases proporcionan un medio ms sencillo de generar
estas formas geomtricas bsicas.
En el ejemplo siguiente se muestra cmo crear y representar una LineGeometry. Como se ha indicado
previamente, un objeto Geometry no puede dibujarse a s mismo, por lo que en el ejemplo se utiliza una forma
Path para representar la lnea. Dado que una lnea no tiene rea, establecer la propiedad Fill de Path no tendra
ningn efecto; en su lugar, se especifican slo las propiedades Stroke y StrokeThickness. En la siguiente
ilustracin se muestra el resultado del ejemplo.
Objeto LineGeometry dibujado desde (10,20) hasta (100,130)
Descripcin
Ejemplo
ArcSegment
BezierSegment
LineSegment
PolyBezierSegment
PolyLineSegment
PolyLineSegment.
PolyQuadraticBezierSegment
Consulte la pgina de
PolyQuadraticBezierSegment.
QuadraticBezierSegment
Los segmentos de PathFigure se combinan en una sola forma geomtrica donde el punto final de cada
segmento es el punto inicial del segmento siguiente. La propiedad StartPoint de PathFigure especifica el punto
desde el que se dibuja el primer segmento. Cada segmento posterior comienza en el punto final del segmento
anterior. Por ejemplo, para definir una lnea vertical de 10,50 a 10,150 se establece la propiedad StartPoint en
10,50 y se crea un LineSegment con un valor de 10,150 para la propiedad Point.
En el ejemplo siguiente se crea un objeto PathGeometry simple compuesto de una sola PathFigure con un
LineSegment y se muestra mediante un elemento Path. La propiedad StartPoint del objeto PathFigure se
establece en 10,20 y LineSegment se define con un punto final de 100,130. En la ilustracin siguiente se
muestra el PathGeometry creado por este ejemplo.
Objeto PathGeometry que contiene un solo elemento LineSegment
El objeto CombinedGeometry y el mtodo Combine realizan una operacin de tipo Boolean para
combinar el rea definida por dos geometras. Se descartan los objetos Geometry que no tienen rea.
nicamente es posible combinar dos objetos Geometry (aunque estas dos geometras tambin pueden
ser geometras compuestas).
La clase GeometryGroup crea una fusin de los objetos Geometry que contiene sin combinar su rea.
Se puede agregar cualquier nmero de objetos Geometry a un GeometryGroup.
Dado que no realizan una operacin de combinacin, el uso de objetos GeometryGroup proporciona ventajas de
rendimiento con respecto al uso de objetos CombinedGeometry o del mtodo Combine.
Geometras combinadas
En la seccin anterior se menciona que el objeto CombinedGeometry y el mtodo Combine combinan el rea
definida por las geometras que contienen. La enumeracin GeometryCombineMode especifica cmo se
combinan las geometras. Los valores posibles para la propiedad GeometryCombineMode son: Union, Intersect,
Exclude y Xor.
En el ejemplo siguiente, se define una CombinedGeometry con el modo de combinacin Union. Tanto
Geometry1 como Geometry2 se definen como crculos del mismo radio, pero con los centros desplazados en 50.
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<!-- Combines two geometries using the union combine mode. -->
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
En el ejemplo siguiente, se define una CombinedGeometry con el modo de combinacin Xor. Tanto Geometry1
como Geometry2 se definen como crculos del mismo radio, pero con los centros desplazados en 50.
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
En la ilustracin anterior, observe que no se rellenan el centro ni el tercer anillo. Esto se debe a que el rayo
dibujado desde cualquier punto situado en el interior de cualquiera de esos dos anillos pasa a travs de un
nmero par de segmentos. Vea la ilustracin siguiente:
Como puede ver, se rellenan todos los anillos. Esto se debe a que todos los segmentos estn dibujados en la
misma direccin y, por tanto, un rayo dibujado desde cualquier punto cruzar uno o ms segmentos, y la suma
de las veces que cruza no ser igual a cero. Por ejemplo, en la ilustracin siguiente, las flechas rojas
representan la direccin en que se dibujan los segmentos y la flecha blanca representa un rayo arbitrario
trazado desde un punto situado en el anillo ms profundo. Partiendo de cero, se suma una unidad cada vez que
el rayo cruza un segmento, porque el segmento cruza el radio de izquierda a derecha.
Para ilustrar mejor el comportamiento de la regla Nonzero, se necesita una forma ms compleja con segmentos
trazados en distintas direcciones. En el cdigo XAML que se muestra a continuacin se crea una forma similar a
la del ejemplo anterior, pero con PathGeometry en lugar de con EllipseGeometry, de manera que se crean
cuatro arcos concntricos en lugar de crculos concntricos totalmente cerrados.
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<GeometryGroup FillRule="NonZero">
<PathGeometry>
<PathGeometry.Figures>
<!-- Inner Ring -->
<PathFigure StartPoint="10,120">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="50,50" IsLargeArc="True" SweepDirection="CounterClockwise"
Point="25,120" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
<!-- Second Ring -->
<PathFigure StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="70,70" IsLargeArc="True" SweepDirection="CounterClockwise"
Observe que no se rellena el tercer arco contando desde el centro. En la ilustracin siguiente se muestra por
qu. En la ilustracin, las flechas rojas representan la direccin en que se dibujan los segmentos. Las dos
flechas blancas representan dos rayos arbitrarios que parten desde un punto situado en la regin "no rellena".
Como se puede apreciar en la ilustracin, la suma de los valores de un rayo determinado que cruza los
segmentos que encuentra en su trayectoria, es cero. Como se ha definido anteriormente, una suma de cero
significa que el punto no forma parte de la geometra (no es parte del relleno) mientras que si la suma es
distinta de cero, aunque sea un valor negativo, s forma parte de la geometra.
Nota: para los fines de FillRule, todas las formas se consideran cerradas. Si existe una abertura en un
segmento, dibuje una lnea imaginaria para cerrarlo. En el ejemplo anterior, hay pequeas aberturas en los
anillos. En semejante caso, cabra esperar que un rayo trazado a travs de las aberturas diese un resultado
distinto que uno que se trazase en otra direccin. A continuacin se muestra una ilustracin ampliada de una de
estas aberturas y el "segmento imaginario" (segmento que se dibuja para aplicar FillRule) que lo cierra.
En el ejemplo siguiente, se crea una imagen idntica pero con una zona de recorte definida. nicamente se
muestra la parte de la imagen que est dentro del rea de EllipseGeometry.
<Image Source="sampleImages\Waterlilies.jpg" Width="200" Height="150"
HorizontalAlignment="Left">
<Image.Clip>
<EllipseGeometry RadiusX="100" RadiusY="75" Center="100,75"/>
</Image.Clip>
</Image>
Imagen con una zona de recorte elptica
En el marcado siguiente, se define una CombinedGeometry con el modo de combinacin Intersect. Tanto
Geometry1 como Geometry2 se definen como crculos del mismo radio, pero con los centros desplazados en 50.
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<!-- Combines two geometries using the intersect combine mode. -->
<CombinedGeometry GeometryCombineMode="Intersect">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
Geometra combinada con el valor Intersect
En el marcado siguiente, se define una CombinedGeometry con el modo de combinacin Union. Tanto
Geometry1 como Geometry2 se definen como crculos del mismo radio, pero con los centros desplazados en 50.
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<!-- Combines two geometries using the union combine mode. -->
<CombinedGeometry GeometryCombineMode="Union">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
Geometra combinada con el valor Union
Se pueden crear formas ms complejas, tales como polgonos y formas con segmentos curvados, utilizando un
objeto PathGeometry. Aunque en este ejemplo se representa una forma en la pantalla mediante un elemento
Path, tambin se pueden utilizar objetos Geometry para describir el contenido de GeometryDrawing o
DrawingContext. Adems, se pueden utilizar para el recorte y las pruebas de posicionamiento.
Otras clases de geometras simples son LineGeometry y EllipseGeometry. Estas geometras, as como otras
complejas, tambin se pueden crear utilizando una clase PathGeometry o StreamGeometry.
En Lenguaje de marcado de aplicaciones extensible (XAML), puede utilizar la sintaxis de atributo para describir
un trazado.
<Path Stroke="Black" StrokeThickness="1"
(Tenga en cuenta que, en realidad, esta sintaxis de atributo crea un objeto StreamGeometry, que es una
versin ligera de PathGeometry.)
En XAML, tambin puede dibujar un segmento de lnea utilizando la sintaxis de elementos de objeto. El cdigo
siguiente equivale al ejemplo de XAML anterior.
PathFigure myPathFigure = new PathFigure();
myPathFigure.StartPoint = new Point(10, 50);
LineSegment myLineSegment = new LineSegment();
myLineSegment.Point = new Point(200, 70);
PathSegmentCollection myPathSegmentCollection = new PathSegmentCollection();
myPathSegmentCollection.Add(myLineSegment);
myPathFigure.Segments = myPathSegmentCollection;
PathFigureCollection myPathFigureCollection = new PathFigureCollection();
myPathFigureCollection.Add(myPathFigure);
En el ejemplo anterior se ha mostrado cmo crear una forma relativamente simple, un tringulo. PathGeometry
tambin se puede utilizar para crear formas ms complejas, incluidos arcos y curvas.
(Tenga en cuenta que, en realidad, esta sintaxis de atributo crea un objeto StreamGeometry, que es una
versin ligera de PathGeometry.)
En XAML, tambin puede dibujar un arco elptico utilizando explcitamente las etiquetas de objeto. El cdigo
siguiente es equivalente al marcado XAML anterior.
<Path Stroke="Black" StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="100,50" RotationAngle="45" IsLargeArc="True"
SweepDirection="CounterClockwise" Point="200,100" />
</PathSegmentCollection>
</PathFigure.Segments>
Aunque en este ejemplo se utiliz un elemento Path para representar RectangleGeometry, hay muchas otras
maneras de utilizar los objetos RectangleGeometry. Por ejemplo, se puede utilizar RectangleGeometry para
especificar la propiedad Clip de UIElement o la propiedad Geometry de GeometryDrawing.
Otras clases de geometras simples son LineGeometry y EllipseGeometry. Estas geometras, as como otras
complejas, tambin se pueden crear utilizando una clase PathGeometry o StreamGeometry.