久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

WPF: WPF 中的 Triggers 和 VisualStateManager

 紫殿 2020-12-02

在之前寫的這篇文章 WPF: 只讀依賴屬性的介紹與實(shí)踐 中,我們介紹了在 WPF 自定義控件中如何添加只讀依賴屬性,,并且使其結(jié)合屬性觸發(fā)器 (Trigger) 來實(shí)現(xiàn)對(duì)控件樣式的改變。事實(shí)上,,關(guān)于觸發(fā)器,,在 WPF 中除了屬性觸發(fā)器,還有事件觸發(fā)器 (EventTrigger) 和數(shù)據(jù)觸發(fā)器 (DataTrigger),。此外,,為了控制控件外觀的切換,除了可以使用觸發(fā)器外,,我們還可以使用 VisualStates 和 VisualStateManager 來完成。

本文接下來會(huì)分別簡單地介紹 Triggers 和 VisualStateManager,并且介紹一下它們的區(qū)別,;了解這些,,將會(huì)有助于我們?cè)陂_發(fā)自定義控件時(shí),能夠明白何時(shí)選擇屬發(fā)器,,何時(shí)選擇 VisualStateManager,。

一、觸發(fā)器 (Triggers)

前面說過,,觸發(fā)器有三類,,它們分別是:

  • 屬性觸發(fā)器 (Trigger/MultiTrigger)

  • 事件觸發(fā)器 (EventTrigger)

  • 數(shù)據(jù)觸發(fā)器 (DataTrigger/MultiDataTrigger)

這些觸發(fā)器的主要作用是:當(dāng)指定屬性的值發(fā)生改變或者事件觸發(fā)時(shí)來更改控件的外觀或行為;而且被觸發(fā)器監(jiān)測(cè)的屬性必須是依賴屬性,,事件必須是路由事件,;它們能夠用在這些地方:DataTemplate, ControlTemplate, Style, 以及控件的 Inline 屬性中。

1,、屬性觸發(fā)器

特點(diǎn):

  1. UIElement 屬性改變時(shí),,執(zhí)行 Trigger;

  2. 必須設(shè)置 Property 和 Value,;必須包括 Setter 對(duì)象(不支持 EventSetter),;

  3. 可以設(shè)置 EnterActions 和 ExitActions;

  4. 當(dāng)條件不符合時(shí),,會(huì)將屬性值還原到原來的值 ,;

例如:

<Style x:Key="ButtonStyle" TargetType="{x:Type Button}"><Style.Triggers><Trigger Property="IsPressed" Value="True"><Setter Property="Opacity" Value="0.5" /></Trigger><Trigger Property="IsEnabled" Value="False"><Setter Property="Foreground" Value="Red" /></Trigger></Style.Triggers></Style>

MultiTrigger

特點(diǎn):元素 (UIElement) 或控件的多個(gè)屬性改變時(shí),執(zhí)行 Trigger,,如:

<Style x:Key="MulitTriggerButtonStyle" TargetType="Button"><Style.Triggers><MultiTrigger><MultiTrigger.Conditions><Condition Property="IsPressed" Value="True" /><Condition Property="Background" Value="BlanchedAlmond" /></MultiTrigger.Conditions><MultiTrigger.Setters><Setter Property="Foreground" Value="Blue" /><Setter Property="BorderThickness" Value="5" /><Setter Property="BorderBrush" Value="Blue" /></MultiTrigger.Setters></MultiTrigger></Style.Triggers></Style>

2. 事件觸發(fā)器

特點(diǎn):

  1. 當(dāng) FrameworkElement 的路由事件(RouteEvent)觸發(fā)時(shí),,執(zhí)行 EventTrigger;

  2. 通常用來執(zhí)行一些動(dòng)畫,;

  3. 不會(huì)還原成原來的值(不像 Property Trigger 一樣),;

例如:

<Border  …><Border.Triggers><EventTrigger RoutedEvent="Mouse.MouseEnter"><BeginStoryboard><Storyboard><ColorAnimation Duration="0:0:1" Storyboard.TargetName="MyBorder" Storyboard.TargetProperty="Color" To="Gray" /></Storyboard></BeginStoryboard></EventTrigger></Border.Triggers></Border>

3. 數(shù)據(jù)觸發(fā)器

特點(diǎn):數(shù)據(jù)綁定源的值符合 Trigger 指定的條件時(shí),執(zhí)行 Trigger,;例如:

<DataTemplate.Triggers><DataTrigger Binding="{Binding Path=Picture}" Value="{x:Null}"><Setter TargetName="viewImage" Property="Source" Value="/Images/noImage.png" />……</DataTrigger></DataTemplate.Triggers>

MultiDataTrigger

特點(diǎn):當(dāng)多個(gè)綁定值符合 Trigger 的 Conditions 指定的條件時(shí),,執(zhí)行 Trigger;例如:

<DataTemplate.Triggers><MultiDataTrigger><MultiDataTrigger.Conditions><Condition Binding="{Binding Path=Picture}" Value="{x:Null}" /><Condition Binding="{Binding Path=Title}" Value="Waterfall" /></MultiDataTrigger.Conditions><MultiDataTrigger.Setters><Setter TargetName="viewImage" Property="Source" Value="/Images/noImage.png"/><Setter TargetName="viewImage" Property="Opacity" Value="0.5" /><Setter TargetName="viewText" Property="Background" Value="Brown" /></MultiDataTrigger.Setters></MultiDataTrigger></DataTemplate.Triggers>

最后,,要說明的是,,對(duì)于控件的內(nèi)聯(lián) (Inline) 屬性,僅能設(shè)置 EventTrigger,,如:

<Button><Button.Triggers><EventTrigger …></EventTrigger></Button.Triggers></Button>

所以,,總結(jié)來看,以上三類觸發(fā)器的使用場景就是當(dāng)控件的屬性值被更改或者事件被觸發(fā)時(shí),,更修改控件的外觀或行為,;并且屬性觸發(fā)器有獨(dú)特的特點(diǎn),,就是在屬性值還原時(shí),樣式也會(huì)隨即恢復(fù),。

理解了這些,,在開發(fā)自定義控件時(shí),我們就可以通過為自定義控件合理地定義依賴屬性,、只讀依賴屬性以及路由事件,,來控制控件的顯示。接下來,,我們來看 VisualStateManager,,它也可以解決同樣的問題。

二,、VisualStateManager

要使用 VisualStateManager,,需要定義 VisualState;在 VisualState 中定義控件的不同的狀態(tài)以及每種狀態(tài)下的樣式,,然后,,在代碼中合適的地方,我們可以使用 VisusalStateManager 類的 GoToState 來切換到對(duì)應(yīng)的狀態(tài),,從而實(shí)現(xiàn)樣式的切換,。

所以,總括地說,,這里涉及了以下四個(gè)方面:

  1. VisualState: 視圖狀態(tài)(Visual States)表示控件在一個(gè)特殊的邏輯狀態(tài)下的樣式,、外觀;

  2. VisualStateGroup: 狀態(tài)組由相互排斥的狀態(tài)組成,,狀態(tài)組與狀態(tài)組并不互斥,;

  3. VisualTransition: 視圖轉(zhuǎn)變 (Visual Transitions) 代表控件從一個(gè)視圖狀態(tài)向另一個(gè)狀態(tài)轉(zhuǎn)換時(shí)的過渡;

  4. VisualStateManager: 由它負(fù)責(zé)在代碼中來切換到不同的狀態(tài),;

每個(gè) VisualState 都屬于一個(gè)狀態(tài)組 (VisualStateGroup),,也即一個(gè) VisualStateGroup 中可以定義多個(gè) VisualState;并且,,我們也可以定義多個(gè) VisualStateGroup,;需要再次強(qiáng)調(diào)的是:同一個(gè) VisualStateGroup 中 VisualState 是互斥的,而不同的 VisualStateGroup 中的 VisualState 是在同一時(shí)刻是可以共存的,。以 Button 為例:

技術(shù)分享圖片

我們看到,,在它里面,定義了三個(gè) VisualStateGroup,,分別是 CommonStates(正常狀態(tài)),、FocusStates(焦點(diǎn)狀態(tài))、ValidationStates(驗(yàn)證狀態(tài)),,而每個(gè) VisualStateGroup 下又有若干個(gè) VisualState,。在 CommonStates 中,,按鈕可以是 Normal 、MouseOver 或 Pressed(只能是三者之一),,但它卻可以結(jié)合其它 VisualStateGroup 中的 VisualState 來顯示,,如按鈕具有焦點(diǎn)時(shí)且鼠標(biāo)移動(dòng)到其上,這就結(jié)合了 MouseOver 與 Focused 兩種狀態(tài),。以下它的部分代碼:

<ControlTemplate TargetType="Button"><Grid><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="CommonStates"><VisualStateGroup.Transitions><VisualTransition GeneratedDuration="0:0:1" To="MouseOver" /><VisualTransition GeneratedDuration="0:0:1" To="Pressed" /><VisualTransition GeneratedDuration="0:0:1" To="Normal" /></VisualStateGroup.Transitions><VisualState x:Name="Normal" /><VisualState x:Name="MouseOver"><Storyboard><ColorAnimationStoryboard.TargetName="BackgroundBorder"Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"To="#A1D6FC"Duration="0" /></Storyboard></VisualState><VisualState x:Name="Pressed"><Storyboard><ColorAnimationStoryboard.TargetName="BackgroundBorder"Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"To="#FCA1A1"Duration="0" /></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Borderx:Name="BackgroundBorder"Background="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"SnapsToDevicePixels="true" /><ContentPresenterMargin="{TemplateBinding Padding}"HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"VerticalAlignment="{TemplateBinding VerticalContentAlignment}"Focusable="False"RecognizesAccessKey="True"SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /></Grid></ControlTemplate>

在自定義控件的開發(fā)過程中,我們也可以采用同樣的原則,,即在 XAML 中定義 VisualStateGroup,、VisualState 以及 VisualTransition(可選),由借助于 VisualStateManager 來實(shí)現(xiàn)切換,。以下是一個(gè)帶水印功能的 TextBox 中 VisualStates 的定義:

<VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="WatermarkGroup"><VisualStateGroup.Transitions><VisualTransition From="ShowWatermarkState" To="HideWatermarkState"><Storyboard><DoubleAnimation Storyboard.TargetName="PART_Watermark"Storyboard.TargetProperty="Opacity" From="1"To="0" Duration="0:0:2" /></Storyboard>                                        </VisualTransition><VisualTransition From="HideWatermarkState" To="ShowWatermarkState"><Storyboard><DoubleAnimation Storyboard.TargetName="PART_Watermark"Storyboard.TargetProperty="Opacity" From="0"To="1" Duration="0:0:2" /></Storyboard></VisualTransition></VisualStateGroup.Transitions><VisualState x:Name="ShowWatermarkState"><Storyboard><ObjectAnimationUsingKeyFrames Duration="0:0:0"Storyboard.TargetName="PART_Watermark"Storyboard.TargetProperty="(UIElement.Visibility)"><DiscreteObjectKeyFrame KeyTime="0:0:0"Value="{x:Static Visibility.Visible}"/></ObjectAnimationUsingKeyFrames></Storyboard></VisualState><VisualState x:Name="HideWatermarkState"><Storyboard><ObjectAnimationUsingKeyFrames Duration="0:0:0"Storyboard.TargetName="PART_Watermark"Storyboard.TargetProperty="(UIElement.Visibility)"><DiscreteObjectKeyFrame KeyTime="0:0:0"Value="{x:Static Visibility.Collapsed}"/></ObjectAnimationUsingKeyFrames></Storyboard></VisualState>                                </VisualStateGroup></VisualStateManager.VisualStateGroups>

可以看出,,它定義了 WatermarkGroup 組,并在其中定義了 ShowWatermarkState 和 HideWatermarkState 兩個(gè) VisualState,,并且,,通過定義的 VisualTransition 能夠?qū)崿F(xiàn)在這兩種狀態(tài)下切換時(shí),水印文本會(huì)有淡入,、淡出的效果,。

最后,在代碼中,,調(diào)用  VisualStateManager.GoToState 方法來切換到合適的狀態(tài)即可:

private void UpdateState(){bool textExists = Text.Length > 0;var watermark = GetTemplateChild("PART_Watermark") as FrameworkElement;var state = textExists || IsFocused ? "HideWatermarkState" : "ShowWatermarkState";VisualStateManager.GoToState(this, state, true);}protected override void OnGotFocus(RoutedEventArgs e){base.OnGotFocus(e);UpdateState();}protected override void OnLostFocus(RoutedEventArgs e){base.OnLostFocus(e);UpdateState();}

最后,,何時(shí)切換狀態(tài)呢?一般情況下,,包括但不限于以下幾個(gè)場合或地方:

  • 在 OnApplyTemplate 方法(即應(yīng)用模板時(shí)),;

  • 當(dāng)某個(gè)屬性改變時(shí)(可以在 PropertyChangedCallback 中調(diào)用);

  • 當(dāng)某個(gè)事件發(fā)生后,; 

三,、Triggers 與 VisualStateManager 的區(qū)別

以上我們看到 Trigger 和 VisualStateManager 都可以完成相同的事,不過它們也是有區(qū)別的,,主要有以下幾點(diǎn):

  1. Triggers 僅僅在 XAML 中使用(盡管它可能要用到我們的自定義屬性或事件,,但對(duì)于更改狀態(tài)這件事來說,我們只要在 XAML 中操作即可),,而 VisualStateManager 則 XAML 和 C# 代碼都需要,;

  2. 對(duì)于 Trigger,定義模板的人可以自由地指定當(dāng)條件符合時(shí)時(shí)該有何種的變化,;而對(duì)于 VisualStateManager,,則需要控件開發(fā)人員定義不同的 VisualState,然后定義模板的人根據(jù)約定(根據(jù) TemplateVisualStateAttribute 特性)來定義在控件不同狀態(tài)下的樣式,;

  3. 對(duì)于 Trigger,,它是對(duì)事件,、屬性或者所綁定的數(shù)據(jù)發(fā)生變化時(shí),作出對(duì)應(yīng)的改變,;而 VSM 則可以自由控制狀態(tài)的切換,,并定在切換時(shí),還可以指定 VisualTransition,;

  4. 最后,, VisualStateManager 不僅支持 WPF,而且也支持 UWP,,我們可以說它是“跨平臺(tái)”的,,而 Trigger 在 UWP 上不被支持。

總結(jié)

本文主要討論了 WPF 中的觸發(fā)器 Triggers 和 VisualStateManager,,在設(shè)計(jì)自定義控件時(shí),,它們都能夠輔以完成控件樣式切換的功能;我們分別介紹了它們二者的使用方法以及使用要點(diǎn),;最后我們也總結(jié)了它們的區(qū)別,。當(dāng)我們了解了它們各自的特點(diǎn)以及它們的區(qū)別后,我們就可以有選擇地,、更方便地來設(shè)計(jì)我們的自定義控件,,并在 WPF 開發(fā)過程中自由地運(yùn)用它們。

參考資料:

VisualStateManager and alternative to Triggers

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多