VisualStateManager使用說明

Demo下載:http://yunpan.cn/cFjgPtWRHKH9H  访问密码 c4b7

顧名思義,視圖狀態管理器。

在WPF中,它的功能似乎更強大。在UWP中,閹割了GotElementState方法,導致它只能在控件內部使用。

這個東東一般用來突出某些操作,以提醒用戶。它原來是狀態A,後來用戶進行了某些操作,我們就會根據用戶的操作,判斷他想要做什麼,然後根據他的目的,顯示狀態B。最容易理解的例子就是按鈕,它普通狀態,鼠標放上去以後,變成了另一種狀態,點擊又是另一種狀態。

1.按鈕狀態

我們先來看看,按鈕有哪些狀態。首先我們來編輯一個按鈕模板:XAML面板中,添加一個按鈕,並在它上面右鍵->編輯模板->編輯副本,截圖如下:

然後,我們就可以得到一個按鈕的副本:

<Style x:Key="ButtonStyle1" TargetType="Button">
            <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}"/>
            <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
            <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundTransparentBrush}"/>
            <Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}"/>
            <Setter Property="Padding" Value="8,4,8,4"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
            <Setter Property="FontWeight" Value="Normal"/>
            <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
            <Setter Property="UseSystemFocusVisuals" Value="True"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid x:Name="RootGrid">
                            <Grid.Background>
                                <SolidColorBrush x:Name="bkBrush" Color="LightGray" />
                            </Grid.Background>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal">
                                        <Storyboard>
                                            <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="PointerOver">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Pressed">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <PointerDownThemeAnimation Storyboard.TargetName="RootGrid"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledTransparentBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>

                    <!------------- 我加的狀態 --------------->
                                    <VisualState x:Name="testState">
                                        <Storyboard>
                                            <ColorAnimation To="Red" Storyboard.TargetName="bkBrush" Storyboard.TargetProperty="Color" Duration="0:0:2" EnableDependentAnimation="True" />
                                        </Storyboard>
                                    </VisualState>

                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>

                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

在上面的代碼中,可以看到鼠標有 "Normal" "PointerOver" "Pressed" "Disabled" 四種狀態。意思一看就知道。

那麼這些狀態是怎麼執行的呢?由誰來執行呢?

為了解答這個問題,我添加了一個狀態 "testState"。我添加了一個按鈕,單擊來調用它。

private void button1_Click(object sender, RoutedEventArgs e)
        {
            Windows.UI.Xaml.VisualStateManager.GoToState(button, "testState", true);
        }

一點擊button1,就使用 GoToState 調用另一個按鈕的狀態。具體效果看我Demo.

那麼我們能調用 PointerOver之類的狀態嗎?答案是肯定的。它由誰來調用,答案也呼之欲出,Button來調用。Button是一個控件,我們只要捕獲鼠標消息,然後在消息處理函數那裡調用 GoToState, 那這一切不就順理成章了嗎?

2.UserControl

所以我又寫了一個UserControl,當鼠標放上去時,改變它的背景顏色。

<UserControl
    x:Class="VisualStateManager.MyUserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:VisualStateManager"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">
    <UserControl.Resources>
        <SolidColorBrush x:Name="RedBrush" Color="Red" />
    </UserControl.Resources>

    <Grid x:Name="rootGrid" PointerEntered="rootGrid_PointerEntered" Background="Gray" PointerExited="rootGrid_PointerExited">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualStateGroup.States>
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="PointerOver">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="rootGrid" Storyboard.TargetProperty="Background">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource RedBrush}" />
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup.States>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</UserControl>

看Grid的消息響應:

PointerEntered="rootGrid_PointerEntered" Background="Gray" PointerExited="rootGrid_PointerExited"
        private void rootGrid_PointerEntered(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Xaml.VisualStateManager.GoToState(this, "PointerOver", true);
        }

        private void rootGrid_PointerExited(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Xaml.VisualStateManager.GoToState(this, "Normal", true);
        }

然後效果就出來了,鼠標一放上去,背景顏色變紅。SO EASY。

但是,如果你仔細看,Normal 狀態,發現它什麼也不做,那為什麼它什麼也不做會還原為原來的灰色背景呢?

3.狀態執行的細節

我們就必須要了解這個細節了:

1. 如果控件要转换到的新State有Storyboard,运行该Storyboard。如果控件的旧State有Storyboard,结束其运行。 
2. 如果控件已处于新state状态(即新旧State相同),则GoToState不执行任何操作并返回true。 
3. 如果新State在控件的ControlTemplate中不存在,则GoToState不执行任何操作并返回 false。

以上細節摘自:http://www.cnblogs.com/KeithWang/archive/2012/03/30/2425588.html

4.觸發器自動跳轉狀態

據我研究,微軟只提供了窗口大小改變,然後觸發狀態。。感覺功能很局限啊。不知道有沒有大神知道更多的,然後偷偷地告訴我。

這個東東,最常用的就是當窗口大小改變時,改變程式的界面佈局。假設有一個圖片瀏覽工具,當窗口寬度為100的時候,你只顯示一列。當窗口寬度為200的時候,你就顯示兩列。

又如微軟的視頻顯示中的那樣,在手機中,操作按鈕放在程式最下方,在PC上,操作按鈕放在最右邊。。這個時候可以使用這個東東。。我寫了一個當窗口寬度大於600時,自動拉伸按鈕長度的狀態:

        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState>
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="600" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="button1.Width" Value="500" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

如果是改變按鈕的位置,如顯示在下方,改變到顯示到右方,可以看我的這篇博客:WIN10-UWP開發之控件。或許看微軟的示例。

好了,就寫到這裡了。

时间: 2024-08-11 07:40:18

VisualStateManager使用說明的相关文章

GlusterFS六大卷模式說明

GlusterFS六大卷說明 第一,分佈卷 在分布式卷文件被随机地分布在整个砖的体积.使用分布式卷,你需要扩展存储,冗余是重要或提供其他硬件/软件层.(簡介:分布式卷,文件通过hash算法随机的分布到由bricks组成的卷上.卷中资源仅在一台服务器上存储,在存储池中非镜像或条带模式.) (In a distributed volumes files are spread randomly across the bricks in the volume. Use distributed volum

都很正常這起碼說明

都很正常這起碼說明都很正常這起碼說明都很正常這起碼說明都很正常這起碼說明都很正常這起碼說 http://p.sfacg.com/p/6770815/http://p.sfacg.com/p/6770818/http://p.sfacg.com/p/6770821/http://p.sfacg.com/p/6770823/http://p.sfacg.com/p/6770825/http://p.sfacg.com/p/6766724/http://p.sfacg.com/p/6766727/ht

[DE2i-150] 重建PCIe_Fundmental範例說明

以下資料的整理主要是做備忘錄,避免以後忘了,順便留給需要的人. ========================================== 本文主要是參考友晶科技的DE2i-150光碟裡面的PCie_Fundmental範例,再重新打造一個新的範例程式. 1 // ============================================================================ 2 // Copyright (c) 2012 by Terasic

JAVA報表finereport二次開發的JS使用說明

一.概述 隨著FineReport的發展,它提供的設計器和伺服器應該能夠滿足您絕大部分的需求,完全實現零編碼的軟體開發,革命性地加快軟體開發速度,提高軟體穩定性.但是需求是千變萬化的,而FineReport所包含的功能是報錶行業中比較普遍的典型的,也許某些個性化的功能通過FineReport軟體無法實現.為此,FineReport支持應用開發人員使用網頁腳本.API介面等對FineReport進行深入的開發與控制,以滿足其個性化的需求.當然,如果您發現您的某個需求必須要編程來實現,建議您先給我們

的決定吧這是不是說明大

的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大的決定吧這是不是說明大 http://

【转】UniGUI Session管理說明

[转]UniGUI Session管理說明 (2015-12-29 15:41:15) 转载▼   分类: uniGUI 台中cmj朋友在uniGUI中文社区QQ群里发布的,转贴至此. UniGUI Session管理說明每一個Session對應一個UniMainModule,一個MainForm因此Session+UniMainModule就可以得到所有Session+使用者的資料以做管理之用 [UniServerModule]   Public區定義    UserList:TList; /

ByteBuffer 指標說明

當使用 java NIO 來讀寫檔案或 socket 時,一定會用到 ByteBuffer,大部份的人一開始會被它提供的許多 method 搞得很混亂,像是 flip.compact,甚至會質疑為什麼是提供這些 method ? 還有,ByteBuffer 中的三個指標 position.limit.capacity 會怎麼移動? 這裡做點簡單的說明. allocate 使用 ByteBuffer 前,一定要先為它向系統要一塊記憶體,如下: ByteBuffer buffer = ByteBuf

【转载】GlusterFS六大卷模式說明

本文转载自翱翔的水滴<GlusterFS六大卷模式說明> GlusterFS六大卷說明 第一,分佈卷 在分布式卷文件被随机地分布在整个砖的体积.使用分布式卷,你需要扩展存储,冗余是重要或提供其他硬件/软件层.(簡介:分布式卷,文件通过hash算法随机的分布到由bricks组成的卷上.卷中资源仅在一台服务器上存储,在存储池中非镜像或条带模式.) (In a distributed volumes files are spread randomly across the bricks in the

open和opener使用說明

父網頁:window.open("article.html") 子網頁:var dialoginfo=$('#dialogdata',window.opener.document); alert(dialoginfo.html()); 說明:此方法只能獲取父窗口原始的信息,無法獲得通過JS設置的信息,且只能獲取html.