背水一戰 Windows 10 (8) - 控件 UI: StateTrigger
作者:webabcd
介紹
背水一戰 Windows 10 之 控件 UI
- VisualState 之 StateTrigger
示例
1、自定義 StateTrigger
Controls/UI/VisualState/MyDeviceFamilyStateTrigger.cs
/* * 用於演示自定義 StateTrigger * * * StateTriggerBase - 自定義 StateTrigger 需要繼承此基類 * SetActive(Boolean IsActive) - 調用此方法,傳遞 true 則應用對應的 VisualState;傳遞 false 則取消對應的 VisualState * * * 此類的作用:當前的設備類型與指定的一致時,則觸發對應的 VisualState * 注:如果 DeviceFamily 屬性需要綁定的話,別忘了將其定義為依賴屬性 */ using Windows.UI.Xaml; namespace Windows10.Controls.UI.VisualState { public class MyDeviceFamilyStateTrigger : StateTriggerBase { private string _deviceFamily; public string DeviceFamily { get { return _deviceFamily; } set { _deviceFamily = value; // 獲取當前的設備類型,目前已知的返回字符串有:Windows.Mobile, Windows.Desktop, Windows.Xbox string currentDeviceFamily = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily; // 當前的設備類型與指定的一致則觸發對應的 VisualState SetActive(_deviceFamily == currentDeviceFamily); } } } }
2、自定義 StateTrigger
Controls/UI/VisualState/MyInputTypeStateTrigger.cs
/* * 用於演示自定義 StateTrigger * * * StateTriggerBase - 自定義 StateTrigger 需要繼承此基類 * SetActive(Boolean IsActive) - 調用此方法,傳遞 true 則應用對應的 VisualState;傳遞 false 則取消對應的 VisualState * * * 此類的作用:當指定的 FrameworkElement 觸發 PointerPressedEvent 事件時,根據 PointerDeviceType 的不同觸發不同的 VisualState * 注:如果 TargetElement 屬性或 PointerType 屬性需要綁定的話,別忘了將其定義為依賴屬性 */ using Windows.Devices.Input; using Windows.UI.Xaml; using Windows.UI.Xaml.Input; namespace Windows10.Controls.UI.VisualState { public class MyInputTypeStateTrigger : StateTriggerBase { private FrameworkElement _targetElement; private PointerDeviceType _lastPointerType, _triggerPointerType; private PointerEventHandler _pointerEventHandler; // 指定的 FrameworkElement public FrameworkElement TargetElement { get { return _targetElement; } set { if (_pointerEventHandler == null) { _pointerEventHandler = new PointerEventHandler(_targetElement_PointerPressed); } if (_targetElement != null) { _targetElement.RemoveHandler(FrameworkElement.PointerPressedEvent, _pointerEventHandler); } _targetElement = value; // 監聽 FrameworkElement 的 PointerPressedEvent 事件 _targetElement.AddHandler(FrameworkElement.PointerPressedEvent, _pointerEventHandler, true); // 這么寫有問題,因為點擊 button 時不會觸發此事件 // _targetElement.PointerPressed += _targetElement_PointerPressed; } } private void _targetElement_PointerPressed(object sender, PointerRoutedEventArgs e) { _lastPointerType = e.Pointer.PointerDeviceType; UpdateTrigger(); } // 指定的 PointerDeviceType(Touch, Pen, Mouse) public PointerDeviceType PointerType { get { return _triggerPointerType; } set { _triggerPointerType = value; } } public void UpdateTrigger() { // 指定的 FrameworkElement 觸發 PointerPressedEvent 事件后,其 PointerDeviceType 如果和指定的 PointerDeviceType 一致,則觸發對應的 VisualState SetActive(_triggerPointerType == _lastPointerType); } } }
3、演示 StateTrigger 的應用
Controls/UI/VisualState/StateTrigger.xaml
<Page x:Class="Windows10.Controls.UI.VisualState.StateTrigger" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Controls.UI.VisualState" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:custom="using:Windows10.Controls.UI.VisualState" > <!-- 本例用於演示 StateTrigger 的應用,以及如何自定義 StateTrigger StateTrigger 的作用就是:當指定的條件達成時觸發對應的 VisualState 內置的 StateTrigger 一共有兩個,分別是 AdaptiveTrigger 和 StateTrigger,他們都繼承自 StateTriggerBase --> <Page.Resources> <Style x:Key="MyTextStyle" TargetType="TextBlock" BasedOn="{StaticResource MyTextBlockStyle}"> <Setter Property="FontSize" Value="24"/> </Style> <ControlTemplate x:Key="MyControlTemplate" TargetType="Button"> <Border BorderBrush="Red" BorderThickness="1"> <Grid Background="{TemplateBinding Background}"> <ContentPresenter Foreground="Red" /> </Grid> </Border> </ControlTemplate> </Page.Resources> <Grid x:Name="myGrid" Background="Transparent"> <StackPanel Name="myPanel" Orientation="Horizontal" Margin="10 0 10 10"> <TextBlock Text="TextBlock 1 " Name="myTextBlock1" Margin="10" /> <TextBlock Text="TextBlock 2 " Name="myTextBlock2" Margin="10" /> <TextBlock Text="TextBlock 3 " Name="myTextBlock3" Margin="10" /> <Button Name="myButton" Content="我是 Button" Margin="10" /> <CheckBox Name="chkIsActive" Content="IsActive" Margin="10" /> </StackPanel> <!--注意:VisualState 不能放到 Page 下面,否則不工作--> <VisualStateManager.VisualStateGroups> <!-- 給 VisualState 分組是很有必要的,每個 VisualStateGroup 正在使用的 VisualState 只能有一個 --> <VisualStateGroup x:Name="WindowSizeStates"> <VisualState> <VisualState.StateTriggers> <!-- AdaptiveTrigger - 內置的 StateTrigger MinWindowWidth - 當窗口的寬度大於等於此值時觸發(依賴屬性) MinWindowHeight - 當窗口的高度大於等於此值時觸發(依賴屬性) --> <!--當窗口的的寬度大於等於 720 時,觸發此 VisualState(這里沒有對應的 VisualState,也就是都恢復為默認狀態)--> <AdaptiveTrigger MinWindowWidth="720" /> </VisualState.StateTriggers> </VisualState> <VisualState> <VisualState.StateTriggers> <!--當窗口的的寬度大於等於 0 時且小於 720 時,觸發此 VisualState--> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="myPanel.Orientation" Value="Vertical" /> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="ActiveStates"> <VisualState> <VisualState.StateTriggers> <!-- StateTrigger - 內置的 StateTrigger IsActive - 是否觸發對應的 VisualState(依賴屬性) --> <!--根據復選框 chkIsActive 的選中狀態,來決定是否觸發此 VisualState--> <StateTrigger IsActive="{Binding ElementName=chkIsActive, Path=IsChecked, Mode=OneWay}" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="myTextBlock1.Style" Value="{StaticResource MyTextStyle}" /> <Setter Target="myTextBlock2.Style" Value="{StaticResource MyTextStyle}" /> <Setter Target="myTextBlock3.Style" Value="{StaticResource MyTextStyle}" /> <Setter Target="myButton.Template" Value="{StaticResource MyControlTemplate}" /> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="DeviceFamilyStates"> <VisualState> <VisualState.StateTriggers> <!-- MyDeviceFamilyStateTrigger - 自定義的 StateTrigger DeviceFamily - 當設備類型為指定的值時觸發(非依賴屬性,如需綁定之類的特性的話,則要將其改為依賴屬性) --> <!--當設備類型為 Windows.Desktop 時觸發此 VisualState--> <custom:MyDeviceFamilyStateTrigger DeviceFamily="Windows.Desktop" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="myGrid.Background" Value="#FF0000" /> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="InputTypeStates"> <VisualState> <!-- MyInputTypeStateTrigger - 自定義的 StateTrigger TargetElement - 需要監聽 PointerPressedEvent 事件的 FrameworkElement 對象(非依賴屬性,如需綁定之類的特性的話,則要將其改為依賴屬性) PointerType - 監聽的 FrameworkElement 觸發 PointerPressedEvent 事件后,根據 PointerType 的類型來決定觸發指定的 VisualState(非依賴屬性,如需綁定之類的特性的話,則要將其改為依賴屬性) --> <!--當觸發了 myButton 的 PointerPressedEvent 事件后,如果其 PointerDeviceType 是 Mouse 類型,則觸發此 VisualState--> <VisualState.StateTriggers> <!--對 {x:Bind myButton} 不理解的話,請參見“綁定”部分--> <custom:MyInputTypeStateTrigger TargetElement="{x:Bind myButton}" PointerType="Mouse" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="myGrid.Background" Value="Orange" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </Page>
OK
[源碼下載]
