VisualStateManager.GoToState(Control, String, Boolean) 方法

定義

藉由依名稱要求新的 VisualState ,轉換兩種狀態之間的控制項。

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

參數

control
Control

控制項要在之間轉換的兩個狀態。

stateName
String

Platform::String

winrt::hstring

要切換的目標狀態。

useTransitions
Boolean

bool

true 表示使用 VisualTransition 在狀態之間轉換。 false 表示略過使用轉換,並直接移至要求的狀態。 預設值為 false

傳回

Boolean

bool

如果控制項成功轉換為新狀態,或已經使用該狀態,則為true;否則為false

範例

此範例示範使用 GoToState 方法在狀態之間轉換的控制邏輯。

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>

備註

控制項邏輯會使用這個方法。 您通常只需要撰寫自訂控制項,或是使用應用層級邏輯來檢視狀態, (例如重新整理應用程式內容以取得應用程式視窗大小變更或方向) 。

當您呼叫這個方法時,預期會有一個 VisualState ,其 x:Name 值符合 您的 stateName 值、控制項範本中由 控制項識別的控制項,或做為應用程式的資源。 如果沒有,您不會收到例外狀況,但傳回值會是 false由 stateName命名的狀態可以位於指定之 Control範本中的任何VisualStateGroup元素中。 您可以追蹤哪些狀態是 VisualStateGroup ,以及知道當您從該群組指定新狀態時卸載哪些狀態。

使用 GoToState 時,通常未特別針對該控制項實例定義包含名稱所參考之視覺狀態的 ControlTemplate 。 相反地,視覺狀態來自預設控制項樣式,會載入為該控制項所有實例的隱含樣式。 如需隱含樣式概念的詳細資訊,請參閱 快速入門:控制項範本

VisualStateManager 支援控制項作者的兩個重要功能,以及將自訂範本套用至控制項的應用程式開發人員:

  • 控制項作者或應用程式開發人員使用VisualStateManager.VisualStateGroups附加屬性,將VisualStateGroup物件元素新增至 XAML 中控制項範本定義的根項目。 在 VisualStateGroup 元素內,每個 VisualState 都代表控制項的離散視覺狀態。 每個 VisualState 都有一個名稱,代表使用者可變更的 UI 狀態,或由控制項邏輯變更。 VisualState主要包含分鏡腳本。 此 Storyboard 會以個別相依性屬性值為目標,每當控制項處於該視覺狀態時,就應該套用這些值。
  • 呼叫 VisualStateManager 的靜態 GoToState方法,控制這些狀態之間的作者或應用程式開發人員轉換。 每當控制項邏輯處理指出狀態變更的事件,或控制項邏輯自行起始狀態變更時,控制項作者就會執行此動作。 控制項定義程式碼通常會執行此動作,而不是應用程式程式碼,因此應用程式程式碼預設會有所有可能的視覺狀態及其轉換和觸發條件。 或者,它是變更視覺狀態的應用程式程式碼,用來管理應用層級檢視狀態,以回應使用者驅動變更主應用程式視窗的大小或方向。

當您呼叫 GoToState 來變更控制項的視覺狀態時, VisualStateManager 會執行下列動作:

  • 首先,它會判斷是否符合 stateName 的狀態是否存在。 如果沒有,則不會發生任何事,而且方法會傳回 false
  • 如果依stateName命名的VisualState存在,而且有Storyboard,腳本就會開始。
  • 如果控制項在新要求狀態之前,從該相同VisualStateGroup 使用的 VisualState 具有Storyboard,該分鏡腳本就會停止。 除了新 VisualState 套用動畫的特定屬性以外,控制項會還原為控制項範本及其組合中最初載入的狀態。

如果控制項已在要求為stateNameVisualState中,GoToState 會傳回true,但不會 (腳本不會重新開機) 。

常見的控制項實作模式是定義控制項類別的單一私用方法,負責處理控制項的所有可能 VisualState 變更。 要使用的視覺狀態是藉由檢查控制項的屬性來決定。 這些屬性可能是公用或私人屬性。 屬性的值會由 OnGotFocus等事件的控制項邏輯中的處理常式調整,並在設定視覺狀態之前立即檢查 Just-In-Time。 本主題中的程式碼範例會使用此實作模式。 或者,您可以從事件處理常式內呼叫個別狀態的 GoToState、從控制項事件處理常式覆寫 (OnEvent 方法) ,或從所有可能變更狀態的協助程式方法呼叫, (使用者驅動事件、自動化事件、初始化邏輯) 。

您也可以從自訂相依性屬性的 PropertyChangedCallback 實作中呼叫 GoToState。

視覺狀態和轉換

除了視覺狀態之外,視覺狀態模型也包含轉換。 轉換是由 腳本 所控制的動畫動作,這些動作會在狀態變更時于每個視覺狀態之間發生。 您可以針對控制項的一組視覺狀態所定義的開始狀態和結束狀態組合,以不同的方式定義轉換。 轉換是由VisualStateGroupTransitions屬性所定義,通常定義于 XAML 中。 大部分的預設控制項範本不會定義轉換,在此情況下,狀態之間的轉換會立即發生。 如需詳細資訊,請參閱 VisualTransition

您也可以定義 VisualTransition ,使其產生隱含轉換。 在VisualTransitionFromTo視覺狀態中特別針對動畫設定任何相依性屬性,且狀態變更中具有不同值的任何相依性屬性,都可以使用隱含轉換動畫來產生動畫效果。 這個產生的動畫會使用插補,在 From 狀態值與這類屬性的 To 狀態值之間轉換。 隱含轉換動畫會持續到VisualTransition的 GeneratedDuration值所陳述的時間。 隱含轉換僅適用于 DoubleColorPoint 值的屬性。 換句話說,屬性必須使用DoubleAnimation、PointAnimationColorAnimation隱含產生動畫效果。 如需詳細資訊,請參閱 GeneratedDuration

視覺狀態變更的事件

當控制項開始轉換 GoToState 呼叫所要求的狀態時,CurrentStateChanging就會引發。 如果 VisualTransition 套用至狀態變更,此事件會在轉換開始時發生。

CurrentStateChanged 會在控制項處於 GoToState 呼叫要求的狀態之後引發,就如同新的 Storyboard 開始一樣。 新分鏡腳本完成時不會引發任何事件。

如果未套用 VisualTransitionCurrentStateChangingCurrentStateChanged 會連續快速引發,但如果兩者都發生,則會依該順序保證。

不過,如果狀態變更轉換遭到新的 GoToState 呼叫中斷,則不會針對第一個狀態轉換引發 CurrentStateChanged 事件。 針對下一個要求的狀態變更,會引發新的事件系列。

不會針對視覺狀態變更叫用OnApplyTemplateOnApplyTemplate 只會針對控制項的初始載入 XAML UI 叫用。

設定自訂控制項的具名視覺狀態

如果您要定義在其控制項範本 XAML 中有視覺狀態的自訂控制項,最佳做法是將控制項類別屬性設定為可控制取用的視覺狀態。 若要這樣做,請在控制項定義程式碼的類別層級套用一或多個 TemplateVisualState 屬性。 每個屬性都應該指定狀態的 x:Name 屬性,也就是控制項取用者傳入 GoToState 呼叫以使用該視覺狀態的 stateName 值。 如果 VisualStateVisualStateGroup的一部分,也應該在屬性定義中指出。

相關概念是控制項作者應該使用 TemplatePartAttribute來屬性主要控制群組件的名稱。 如果控制項取用者想要在套用範本之後從範本範圍存取具名元件,這會很有説明。 TemplateVisualStateAttributeTemplatePartAttribute 合併說明定義控制項的控制項合約。

自訂 VisualStateManager

在進階案例中,您可以從 VisualStateManager 衍生,並變更預設的 GoToState 行為。 衍生類別應該覆寫受保護的 GoToStateCore 方法。 呼叫自訂 VisualStateManager 的任何實例時,都會使用此 Core 邏輯。

應用程式檢視狀態的視覺狀態

自訂控制項不一定有視覺狀態。 您可以使用新控制項範本的視覺狀態,這些範本會套用至您要藉由設定Template屬性來取代預設範本的任何控制項實例。 若要進行這項設定,您必須定義您打算使用的控制項範本和視覺狀態,做為 或 Application.Resources 中的 Page.Resources樣式資源。 最好從預設範本的複本開始,並只修改範本的某些層面,甚至只修改某些視覺狀態,並單獨保留基本組合。 如需詳細資訊,請參閱快速入門:控制項範本

視覺狀態可用來變更 頁面內頁面 的屬性或控制項,以考慮應用程式視窗方向。 您的組合或控制項的版面配置相關屬性值可能會根據整體方向為直向或橫向而變更。 如需 GoToState 此案例的詳細資訊,請參閱 快速入門:針對不同的視窗大小設計應用程式

不是控制項之專案的視覺狀態

有時候,視覺狀態對於您想要變更某些 UI 區域的狀態不是立即 成為 Control 子類別的案例很有用。 您無法直接執行這項操作,因為 GoToState 方法的 控制項 參數需要 Control 子類別,這是指 VisualStateManager 作用的物件。 PageControl 子類別,而且您很少會在沒有 Page的內容中顯示 UI,或者 Window.Content 根目錄不是 Control 子類別。 我們建議您將自訂 UserControl 定義為 Window.Content 根目錄,或是您想要將狀態套用至 (的容器,例如 Panel) 。 然後,您可以在 UserControl 上呼叫 GoToState,並套用狀態,而不論其餘的內容是否為 Control。 例如,您可以將視覺狀態套用至只包含 SwapChainPanel 的 UI,只要您將它放在 UserControl 中,並宣告要套用至父 UserControl 或範本中具名 SwapChainPanel 部分的屬性的具名狀態即可。

適用於

另請參閱