[UWP]创建自定义VisualState Trigger

这篇博客将介绍在UWP程序中如何创建和使用自定义VisualState Trigger。

上一篇博客中介绍了如何使用AdaptiveTrigger。目前UWP内置的StateTrigger只有AdaptiveTrigger一个,当MinWindowWidth/MinWindowHeight发生改变时,执行一些自适应布局。现在有这样一个场景,UWP程序在Mobile和Desktop上运行时显示不同的文字,这个时候就需要用到自定义StateTrigger了。

先分析一下系统自带的AdaptiveTrigger,

using Windows.Foundation;
using Windows.Foundation.Metadata;

namespace Windows.UI.Xaml
{
    //
    // Summary:
    //     Represents a declarative rule that applies visual states based on window properties.
    [Composable(typeof(IAdaptiveTriggerFactory), CompositionType.Public, 65536, "Windows.Foundation.UniversalApiContract")]
    [ContractVersion(typeof(UniversalApiContract), 65536)]
    [MarshalingBehavior(MarshalingType.Agile)]
    [Static(typeof(IAdaptiveTriggerStatics), 65536, "Windows.Foundation.UniversalApiContract")]
    [Threading(ThreadingModel.Both)]
    [WebHostHidden]
    public class AdaptiveTrigger : StateTriggerBase, IAdaptiveTrigger
    {
        //
        // Summary:
        //     Initializes a new instance of the AdaptiveTrigger class
        public AdaptiveTrigger();

        //
        // Summary:
        //     Identifies the MinWindowHeight dependency property.
        //
        // Returns:
        //     The identifier for the MinWindowHeight dependency property.
        public static DependencyProperty MinWindowHeightProperty { get; }
        //
        // Summary:
        //     Identifies the MinWindowWidth dependency property.
        //
        // Returns:
        //     The identifier for the MinWindowWidth dependency property.
        public static DependencyProperty MinWindowWidthProperty { get; }
        //
        // Summary:
        //     Gets or sets the minimum window height at which the VisualState should be applied.
        //
        // Returns:
        //     The minimum window height (in effective pixels) at which the VisualState should
        //     be applied.
        public System.Double MinWindowHeight { get; set; }
        //
        // Summary:
        //     Gets or sets the minimum window width at which the VisualState should be applied.
        //
        // Returns:
        //     The minimum window width (in effective pixels) at which the VisualState should
        //     be applied.
        public System.Double MinWindowWidth { get; set; }
    }
}

AdaptiveTrigger继承了StateTriggerBase,那么我们自定义的State Trigger继承StateTriggerBase即可。

enum DeviceType
{
    Unknown = 0,

    Desktop = 1,

    Mobile = 2,
}


using Windows.Foundation.Collections;
using Windows.UI.Xaml;

namespace CustomStateTrigger
{
    class DeviceTypeAdaptiveTrigger : StateTriggerBase
    {
        public DeviceType PlatformType
        {
            get { return (DeviceType)GetValue(PlatformTypeProperty); }
            set { SetValue(PlatformTypeProperty, value); }
        }

        public static readonly DependencyProperty PlatformTypeProperty =
            DependencyProperty.Register("PlatformType", 
                typeof(DeviceType), 
                typeof(DeviceTypeAdaptiveTrigger), 
                new PropertyMetadata(DeviceType.Unknown, OnDeviceTypePropertyChanged));

        private static void OnDeviceTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DeviceTypeAdaptiveTrigger dat = (DeviceTypeAdaptiveTrigger)d;

            DeviceType type = (DeviceType)e.NewValue;

            IObservableMap<string,string> qualifiers = 
                Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().QualifierValues;

            if(dat != null)
            {
                if(qualifiers.ContainsKey("DeviceFamily") &&
                    qualifiers["DeviceFamily"] == "Mobile")
                {
                    dat.SetActive(type == DeviceType.Mobile);
                }

                if (qualifiers.ContainsKey("DeviceFamily") &&
                    qualifiers["DeviceFamily"] == "Desktop")
                {
                    dat.SetActive(type == DeviceType.Desktop);
                }
            }
        }
    }
}

这样我们自定义的一个StateTrigger就完成了。下面在XAML中应用这个自定义的StateTrigger。

<Page
    x:Class="CustomStateTrigger.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CustomStateTrigger"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Triggers="using:CustomStateTrigger"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock x:Name="DeviceTextBlock" VerticalAlignment="Center" HorizontalAlignment="Center" />

        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="DeviceState">
                <VisualState x:Name="DesktopState">
                    <VisualState.StateTriggers>
                        <Triggers:DeviceTypeAdaptiveTrigger PlatformType="Desktop" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="DeviceTextBlock.Text" Value="Desktop" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="MobileState">
                    <VisualState.StateTriggers>
                        <Triggers:DeviceTypeAdaptiveTrigger PlatformType="Mobile" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="DeviceTextBlock.Text" Value="Mobile" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</Page>

运行结果:

在Github上有一个UWP的WindowsStateTriggers,里面都是一些自定义的StateTrigger,

https://github.com/dotMorten/WindowsStateTriggers

posted @ 2016-12-06 16:39  Yang-Fei  阅读(1506)  评论(1编辑  收藏  举报