VisualStateManager.GoToState(Control, String, Boolean) Método
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Realiza una transición de un control entre dos estados mediante la solicitud de un nuevo Objeto VisualState por nombre.
public:
static bool GoToState(Control ^ control, Platform::String ^ stateName, bool useTransitions);
static bool GoToState(Control const& control, winrt::hstring const& stateName, bool const& useTransitions);
public static bool GoToState(Control control, string stateName, bool useTransitions);
function goToState(control, stateName, useTransitions)
Public Shared Function GoToState (control As Control, stateName As String, useTransitions As Boolean) As Boolean
Parámetros
- control
- Control
Control del que se va a realizar la transición entre estados.
- stateName
-
String
Platform::String
winrt::hstring
El estado al que se realiza la transición.
- useTransitions
-
Boolean
bool
true para usar visualTransition para realizar la transición entre estados. false para omitir el uso de transiciones y ir directamente al estado solicitado. El valor predeterminado es false.
Devoluciones
bool
True si el control realiza correctamente la transición al nuevo estado o ya estaba usando ese estado; de lo contrario, false.
Ejemplos
En este ejemplo se muestra la lógica de control que usa el método GoToState para realizar la transición entre estados.
private void UpdateStates(bool useTransitions)
{
if (Value >= 0)
{
VisualStateManager.GoToState(this, "Positive", useTransitions);
}
else
{
VisualStateManager.GoToState(this, "Negative", useTransitions);
}
if (isFocused)
{
VisualStateManager.GoToState(this, "Focused", useTransitions);
}
else
{
VisualStateManager.GoToState(this, "Unfocused", useTransitions);
}
}
Private Sub UpdateStates(ByVal useTransitions As Boolean)
If Value >= 0 Then
VisualStateManager.GoToState(Me, "Positive", useTransitions)
Else
VisualStateManager.GoToState(Me, "Negative", useTransitions)
End If
If isFocused Then
VisualStateManager.GoToState(Me, "Focused", useTransitions)
Else
VisualStateManager.GoToState(Me, "Unfocused", useTransitions)
End If
End Sub
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NumericUpDownCustomControl"
>
<Style TargetType="local:NumericUpDown">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:NumericUpDown">
<Grid Margin="3"
Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ValueStates">
<!--Make the Value property red when it is negative.-->
<VisualState x:Name="Negative">
<Storyboard>
<ColorAnimation To="Red"
Storyboard.TargetName="TextBlock"
Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)"/>
</Storyboard>
</VisualState>
<!--Return the control to its initial state by
return the TextBlock Foreground to its
original color.-->
<VisualState x:Name="Positive" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<!--Add a focus rectangle to highlight the entire control
when it has focus.-->
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisual"
Storyboard.TargetProperty="Visibility" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<!--Return the control to its initial state by
hiding the focus rectangle.-->
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border BorderThickness="1" BorderBrush="Gray"
Margin="7,2,2,2" Grid.RowSpan="2"
Background="#E0FFFFFF"
VerticalAlignment="Center"
HorizontalAlignment="Stretch">
<TextBlock x:Name="TextBlock" TextAlignment="Center" Padding="5"
Foreground="{TemplateBinding Foreground}"/>
</Border>
<RepeatButton Content="Up" Margin="2,5,5,0"
x:Name="UpButton"
Grid.Column="1" Grid.Row="0"
Foreground="Green"/>
<RepeatButton Content="Down" Margin="2,0,5,5"
x:Name="DownButton"
Grid.Column="1" Grid.Row="1"
Foreground="Green"/>
<Rectangle Name="FocusVisual" Grid.ColumnSpan="2" Grid.RowSpan="2"
Stroke="Red" StrokeThickness="1"
Visibility="Collapsed"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Comentarios
Esta lógica de control usa este método. Normalmente, solo lo necesita si está escribiendo un control personalizado o si usa lógica de nivel de aplicación para los estados de vista (como actualizar el contenido de la aplicación para los cambios en el tamaño o la orientación de la ventana de la aplicación).
Al llamar a este método, se espera que haya un objeto VisualState con un valor x:Name que coincida con el valor stateName , en algún lugar de la plantilla de control para el control identificado por control o como un recurso para la aplicación. Si no lo hay, no obtiene excepciones, pero el valor devuelto será false. El estado denominado por stateName puede estar en cualquiera de los elementos VisualStateGroup de la plantilla para el control especificado. Es necesario realizar un seguimiento de los estados en los que VisualStateGroup y saber qué estado se descarga al especificar un nuevo estado de ese grupo.
Normalmente, la clase ControlTemplate que contiene los estados visuales a los que se hace referencia por nombre cuando se usa GoToState no se define específicamente para esa instancia de control. En su lugar, los estados visuales proceden del estilo de control predeterminado que se carga como estilo implícito para todas las instancias de ese control. Para obtener más información sobre el concepto de estilo implícito, consulte Inicio rápido: Plantillas de control.
VisualStateManager admite dos características importantes para los autores de controles y para los desarrolladores de aplicaciones que aplican una plantilla personalizada a un control:
- Los autores de controles o desarrolladores de aplicaciones agregan elementos de objeto VisualStateGroup al elemento raíz de una definición de plantilla de control en XAML mediante la propiedad adjunta VisualStateManager.VisualStateGroups . Dentro de un elemento VisualStateGroup , cada Objeto VisualState representa un estado visual discreto de un control. Cada Objeto VisualState tiene un nombre que es representativo de un estado de interfaz de usuario que el usuario puede cambiar o cambiar por lógica de control. Un objeto VisualState consta principalmente de un Guión gráfico. Este Guión gráfico tiene como destino los valores de propiedad de dependencia individuales que se deben aplicar cada vez que el control está en ese estado visual.
- Los autores de controles o desarrolladores de aplicaciones realizan la transición entre estos estados mediante una llamada al método GoToState estático de VisualStateManager. Los autores de controles lo hacen cada vez que la lógica de control controla eventos que indican un cambio de estado o la lógica de control inicia un cambio de estado por sí mismo. Es más común que el código de definición de control haga esto en lugar del código de la aplicación, de modo que todos los estados visuales posibles y sus transiciones y condiciones de desencadenador estén allí de forma predeterminada para el código de la aplicación. O bien, es el código de la aplicación que está cambiando los estados visuales, para administrar los estados de vista de nivel de aplicación en respuesta a los cambios controlados por el usuario en el tamaño o la orientación de la ventana principal de la aplicación.
Cuando se llama a GoToState para cambiar el estado visual de un control, VisualStateManager realiza estas acciones:
- En primer lugar, se determina si existe un estado que coincide con stateName . Si no es así, no sucede nada y el método devuelve false.
- Si el objeto VisualState denominado por stateName existe y tiene un Guión gráfico, comienza el guión gráfico.
- Si el objeto VisualState que el control usaba desde ese mismo VisualStateGroup antes del estado recién solicitado tiene un Guión gráfico, ese guión gráfico se detiene. Aparte de las propiedades específicas a las que el nuevo Objeto VisualState aplica una animación, el control vuelve a los estados cargados inicialmente de la plantilla de control y su composición.
Si el control ya está en visualState solicitado como stateName, GoToState devuelve true, pero no hay ninguna acción (el guión gráfico no se reiniciará).
Un patrón de implementación de control común es definir un único método privado de la clase de control que se encarga de todos los posibles cambios de VisualState para el control. El estado visual que se va a usar se determina comprobando las propiedades del control. Estas propiedades pueden ser públicas o privadas. Los controladores ajustan los valores de las propiedades en la lógica de control para eventos como OnGotFocus y se comprueban just-in-time inmediatamente antes de establecer el estado visual. En el ejemplo de código de este tema se usa este patrón de implementación. Como alternativa, puede llamar a GoToState para estados individuales desde controladores de eventos, desde invalidaciones del controlador de eventos de control (los métodos OnEvent ) o desde métodos auxiliares a los que llaman todos los posibles impulsos para los estados cambiantes (eventos controlados por el usuario, eventos de automatización, lógica de inicialización).
También puede llamar a GoToState desde la implementación propertyChangedCallback para una propiedad de dependencia personalizada.
Estados visuales y transiciones
Además de los estados visuales, el modelo de estado visual también incluye transiciones. Las transiciones son acciones de animación controladas por un Guión gráfico que se produce entre cada estado visual cuando se cambia el estado. La transición se puede definir de forma diferente para cada combinación de estado inicial y estado final según lo definido por el conjunto de estados visuales del control. Las transiciones se definen mediante la propiedad Transitions de VisualStateGroup y normalmente se definen en XAML. La mayoría de las plantillas de control predeterminadas no definen transiciones y, en este caso, las transiciones entre estados se producen instantáneamente. Para obtener más información, consulta VisualTransition.
También se puede definir una visualTransition de modo que genere una transición implícita. Cualquier propiedad de dependencia que se dirija específicamente a la animación en los estados visuales From oTo de un objeto VisualTransition y que tenga valores diferentes en el cambio de estado se puede animar con una animación de transición implícita. Esta animación generada pasa entre el valor de estado From y el valor de estado To de dicha propiedad mediante interpolación. La animación de transición implícita dura el tiempo indicado por el valor GeneratedDuration de un objeto VisualTransition. Las transiciones implícitas solo se aplican a las propiedades que son un valor Double, Color o Point . Es decir, la propiedad debe ser posible animar implícitamente mediante doubleAnimation, PointAnimation o ColorAnimation. Para obtener más información, consulta GeneratedDuration.
Eventos para cambios de estado visual
CurrentStateChanging se desencadena cuando el control comienza a realizar la transición de estados según lo solicitado por la llamada a GoToState. Si se aplica un objeto VisualTransition al cambio de estado, este evento se produce cuando comienza la transición.
CurrentStateChanged se activa después de que el control esté en el estado solicitado por la llamada a GoToState, al igual que comienza el nuevo Guión gráfico . No se desencadena ningún evento en la finalización del nuevo guión gráfico.
Si no se aplica una visualTransition , CurrentStateChanging y CurrentStateChanged se activan en sucesión rápida, pero se garantizan en ese orden si se producen ambos.
Sin embargo, si una nueva llamada a GoToState interrumpe una transición de cambio de estado, el evento CurrentStateChanged nunca se genera para la primera transición de estado. Se desencadena una nueva serie de eventos para el siguiente cambio de estado solicitado.
OnApplyTemplate no se invoca para cambios de estado visual. OnApplyTemplate solo se invoca para la carga inicial de un control en una interfaz de usuario XAML.
Atribuir los estados visuales con nombre de un control personalizado
Si va a definir un control personalizado que tiene estados visuales en su XAML de plantilla de control, se recomienda atribuir la clase de control para indicar a los consumidores qué estados visuales están disponibles. Para ello, aplique uno o varios atributos TemplateVisualState en el nivel de clase del código de definición de control. Cada atributo debe especificar el atributo x:Name del estado, que es el valor stateName que un consumidor de control pasaría una llamada a GoToState para usar ese estado visual. Si VisualState forma parte de un objeto VisualStateGroup, también debe indicarse en la definición de atributo.
Un concepto relacionado es que los autores de controles deben atribuir los nombres de los elementos de control clave mediante TemplatePartAttribute. Esto es muy útil si los consumidores de control quieren acceder a elementos con nombre desde el ámbito de la plantilla después de aplicar la plantilla. TemplateVisualStateAttribute y TemplatePartAttribute ayudan combinadas a definir el contrato de control para un control.
VisualStateManager personalizado
Como escenario avanzado, es posible derivar de VisualStateManager y cambiar el comportamiento predeterminado de GoToState. La clase derivada debe invalidar el método GoToStateCore protegido. Cualquier instancia del VisualStateManager personalizado usa esta lógica core cuando se llama a su método GoToState.
Estados visuales para los estados de vista de la aplicación
Los estados visuales no son necesariamente para los controles personalizados. Puede usar estados visuales de nuevas plantillas de control que aplique a cualquier instancia de Control en la que reemplace la plantilla predeterminada estableciendo la propiedad Template . Para configurarlo, debe definir la plantilla de control y los estados visuales en los que planea usar como un recurso style que se encuentra en Page.Resources
o Application.Resources
. Siempre es mejor empezar con una copia de la plantilla predeterminada y modificar solo ciertos aspectos de la plantilla o incluso modificar algunos de los estados visuales y dejar solo la composición básica. Para obtener más información, consulta Inicio rápido: plantillas de control.
Los estados visuales se pueden usar para cambiar las propiedades de una página o controles dentro de la página para tener en cuenta la orientación de la ventana de la aplicación. La composición o los valores de propiedad relacionados con el diseño del control pueden cambiar en función de si la orientación general es vertical o horizontal. Para obtener más información sobre este escenario para GoToState, consulte Inicio rápido: Diseño de aplicaciones para diferentes tamaños de ventana.
Estados visuales de los elementos que no son controles
Los estados visuales a veces son útiles para escenarios en los que desea cambiar el estado de algún área de la interfaz de usuario que no es inmediatamente una subclase Control . No puede hacerlo directamente porque el parámetro de control del método GoToState requiere una subclase Control , que hace referencia al objeto sobre el que actúa VisualStateManager . Page es una subclase Control y es bastante poco frecuente que se muestre la interfaz de usuario en un contexto en el que no tenga una página o que la raíz Window.Content no sea una subclase Control . Se recomienda definir un UserControl personalizado para que sea la raíz Window.Content o ser un contenedor para otro contenido al que quiera aplicar estados (por ejemplo, un Panel). A continuación, puede llamar a GoToState en userControl y aplicar estados independientemente de si el resto del contenido es un control. Por ejemplo, podría aplicar estados visuales a la interfaz de usuario que, de lo contrario, consta de un SwapChainPanel siempre y cuando lo haya colocado dentro de userControl y declarado estados con nombre que se aplican a las propiedades del UserControl primario o de la parte swapChainPanel denominada de la plantilla.