語言

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);
    }

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

備註

此方法被控制邏輯所採用。 通常只有在撰寫自訂控制項,或使用應用程式層級的視圖邏輯(例如刷新應用程式內容以調整視窗大小或方向)時才需要它。

當你呼叫這個方法時,預期會有一個與x:Name你值相符的 VisualState,或作為你應用程式的資源,存在於控制範本control中某處,與你的stateName值相符。 如果沒有例外,你不會有例外,但回傳值會是 false。 所命名的stateName狀態可以位於指定控制模板中的任何 VisualStateGroup 元素中。 你必須記住哪些狀態在哪 VisualStateGroup 個狀態,並且知道當你從該群組指定新狀態時,哪些狀態會被卸載。

通常,使用時GoToState包含視覺狀態的 ControlTemplate 並未為該控制實例特別定義。 取而代之的是,視覺狀態來自預設的控制風格,而該控制方式則被載入為所有該控制實例的隱含風格。 欲了解更多隱式樣式概念,請參閱 XAML 控制範本。

VisualStateManager 支援兩個重要功能,供控制權作者使用,以及應用自訂範本的應用程式開發者使用:

  • 控制項作者或應用程式開發者會利用附加屬性VisualStateManager.VisualStateGroups,將 VisualStateGroup 物件元素加入 XAML 控制範本定義的根元素。 在元素中 VisualStateGroup ,每個 視覺狀態 代表控制項的一個離散視覺狀態。 每個 VisualState UI 狀態都有一個名稱,代表使用者可更改或控制邏輯的 UI 狀態。 A VisualState 主要包含分 鏡圖。 此功能 Storyboard 針對應在控制項處於該視覺狀態時套用的個別相依屬性值。
  • 控制項作者或應用程式開發者透過呼叫 VisualStateManager 的靜態 GoToState 方法來在這些狀態間切換。 控制權作者會在控制邏輯處理表示狀態變更的事件,或控制邏輯自行發起狀態變更時,進行此操作。 控制定義程式碼比應用程式程式碼更常見,這樣所有可能的視覺狀態、轉換和觸發條件在應用程式程式碼中預設都存在。 或者,是應用程式程式碼改變視覺狀態,以管理應用程式層級的視圖狀態,以回應使用者驅動的主視窗大小或方向變化。

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

  • 首先要判斷是否存在一個匹配 stateName 的狀態。 若不行,則不會發生任何事,方法返回 false。
  • 如果 所命名stateName的 VisualState 存在且有分鏡,分鏡就會開始。
  • 如果控制項在新請求狀態前使用該 VisualStateGroup 的 VisualState 有 Storyboard,該 storyboard 就會停止。 除了新版 VisualState 套用動畫的特定屬性外,控制項會回復到控制模板及其組合中最初載入的狀態。

如果控制項已經在 stateName 請求的 VisualState 中,GoToState則返回 true,但除此之外沒有動作(故事板不會重新啟動)。

一個常見的控制實作模式是定義控制類別的單一私有方法,負責處理控制項所有可能的 視覺狀態 變更。 使用哪種視覺狀態是透過檢查控制項的屬性來決定的。 這些房產可能是公共或私人。 屬性值由控制邏輯中的處理程式針對事件(如 OnGotFocus)進行調整,並在設定視覺狀態前即時檢查。 本主題中的程式碼範例即使用此實作模式。 或者,你也可以從事件處理程序內呼叫個別狀態,或從控制事件處理程序的覆寫( OnEvent 方法),或是由各種可能的狀態變更動機(使用者驅動事件、自動化事件、初始化邏輯)呼叫的輔助方法。

你也可以在 PropertyChangedCallback 實作中呼叫 GoToState 來自訂相依屬性。

視覺狀態與轉換

除了視覺狀態外,視覺狀態模型還包含轉換。 轉場是由 分鏡 控制的動畫動作,當狀態改變時,會在每個視覺狀態之間發生。 轉換可以根據你控制組的視覺狀態組合,根據起始狀態和結束狀態的組合來定義不同的方式。 轉換由 VisualStateGroup 的 Transitions 屬性定義,通常在 XAML 中定義。 大多數預設控制範本並未定義轉換,而在此情況下,狀態之間的轉換是瞬間發生的。 更多資訊請參見 VisualTransition。

VisualTransition 也可以定義為產生隱含的轉換。 任何專門針對 A VisualTransition 的 From 或To 視覺狀態動畫,且在狀態變化中值不同的相依屬性,都可以用隱含的轉換動畫來製作。 此動畫透過插值在 From 狀態值與 To 狀態值之間轉換。 隱含的過渡動畫持續時間為 的 GeneratedDuration 值 VisualTransition。 隱含轉換僅適用於 Double、 Color 或 Point 值的屬性。 換句話說,該屬性必須能夠透過 DoubleAnimation、 PointAnimation 或 ColorAnimation 隱含地進行動畫。 更多資訊請參見 GeneratedDuration。

視覺狀態變化事件

當控制項開始依呼叫要求轉換狀態GoToState時,CurrentStateChanging 會觸發。 若對狀態變更套用 VisualTransition ,則此事件會在轉換開始時發生。

CurrentStateChanged 會在控制項依呼叫進入該 GoToState 狀態後觸發,正好在新 故事板 開始時。 新分鏡完成時不會觸發任何事件。

若未套用 VisualTransition,CurrentStateChanging 與 CurrentStateChanged 會連續觸發,但若兩者同時發生,則保證依此順序觸發。

然而,若狀態變更轉換被新 GoToState 呼叫中斷,第一個狀態轉換時不會觸發 CurrentStateChanged 事件。 下一個請求的州變更會觸發一個新的事件系列。

OnApplyTemplate 不會用於視覺狀態變更。 OnApplyTemplate 僅在將控制項載入 XAML UI 初期時被呼叫。

賦予自訂控制項命名的視覺狀態

如果你在定義一個自訂控制,且其控制範本 XAML 中有視覺狀態,最佳做法是將控制類別歸因,以指示控制消費者可用的視覺狀態。 為此,請在控制定義程式碼的類別層級套用一個或多個 TemplateVisualState 屬性。 每個屬性都應該指定狀態的 x:Name 屬性,也就是控制消費者在呼叫GoToState時會傳遞的 stateName 值,以使用該視覺狀態。 如果 VisualState 是 VisualStateGroup 的一部分,這也應該在屬性定義中標示。

相關概念是控制作者應使用 TemplatePartAttribute 為關鍵控制部分命名。 如果控制消費者想在模板套用後從模板範圍存取命名部分,這非常有幫助。 TemplateVisualStateAttribute 與 TemplatePartAttribute 結合後,有助於定義控制項的控制合約。

Custom VisualStateManager

作為進階情境,可以從 VisualStateManager 衍生並更改預設 GoToState 行為。 衍生類別應該會覆寫受保護的 GoToStateCore 方法。 任何自訂 VisualStateManager 的實例在呼叫其GoToState方法時都會使用這個核心邏輯。

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

視覺狀態不一定是用來自訂控制的。 你可以使用新控制範本的視覺狀態,套用到任何替換預設範本的 控制 實例,方法是設定 Template 屬性。 要設定這個,你必須定義你打算用來作為 風格 資源的控制範本和視覺狀態,並且這些資源都在 Page.ResourcesApplication.Resources或 中。 最好先從預設範本的複製品開始,只修改模板的某些部分,甚至只是修改部分視覺狀態,保留基本構圖。 欲了解更多資訊,請參閱 XAML 控制範本。

視覺狀態可用來改變 頁面 或頁面內控制項的屬性,以反映應用程式視窗的方向。 你的構圖或控制器的佈局屬性值可能會因整體方向是直向還是橫向而改變。 關於此情境 GoToState的更多資訊,請參見 XAML 的響應式佈局。

非控制項元素的視覺狀態

視覺狀態有時對於想改變 UI 中某個非 Control 子類別區域狀態的情境很有用。 你無法直接這麼做,因為方法的GoToState控制參數需要一個Control子類別,而子類別指的是 VisualStateManager 所作用的物件。 Page 是一個 Control 子類別,而且你很少會在沒有 Page、 或你的 Window.Content 根節點不是 Control 子類別的情況下顯示 UI。 我們建議你定義一個自訂 的 UserControl ,要麼是 Window.Content 根目錄,要麼是你想套用狀態的其他內容(例如 Panel)的容器。 接著你可以呼叫 GoToState 並 UserControl 套用州,不論其他內容是否為 Control。 例如,你可以將視覺狀態套用到原本只有 SwapChainPanel 的 UI 裡,只要你把它放在 UserControl 你並宣告的命名狀態裡,這些狀態套用到父 UserControl 或模板中命名 SwapChainPanel 部分的屬性。

適用於

另請參閱