在WinRT中获取当前的VisualState

时间:2013-01-31 17:59:09

标签: windows-runtime winrt-xaml visualstatemanager

我正在尝试获取对象的当前VisualState。我找到了一个答案,这是不可能的,另一个博客在其他地方,我应该能够得到这样的:

var currentState = VisualStateManager.GetVisualStateGroups(ContainerGrid);

然而,curentState似乎没有得到任何东西。我做错了什么?

3 个答案:

答案 0 :(得分:2)

我发现这个答案对我来说更好,因为我不需要任何外在的东西:Silverlight: VisualStateManager.GetVisualStateGroups doesn't, How can I get them?

答案 1 :(得分:1)

WinRT XAML工具包具有此扩展方法 - AwaitableUI.ControlExtensions.GoToVisualStateAsync(),可以使用您提到的方法(VisualStateManager.GetVisualStateGroups())查找用于可视状态转换的故事板,并在调用常规VisualStateManager.GoToState()后等待其完成方法。到目前为止,它对我来说很好。唯一需要注意的是,您需要在指定可视状态组的元素上调用GetVisualStateGroups(),因此在大多数情况下,您可能需要深入了解控件模板的可视树,因为这是他们通常定义的位置 - 模板中比实际逻辑控制更深的地方。

以下是我的完整示例课程:

using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;

namespace WinRTXamlToolkit.AwaitableUI
{
    /// <summary>
    /// Extension methods for Control class.
    /// </summary>
    public static class ControlExtensions
    {
        #region GoToVisualStateAsync()
        /// <summary>
        /// Goes to specified visual state, waiting for the transition to complete.
        /// </summary>
        /// <param name="control">
        /// Control to transition.
        /// </param>
        /// <param name="visualStatesHost">
        /// FrameworkElement that defines the visual states
        /// (usually the root of the control's template).
        /// </param>
        /// <param name="stateGroupName">
        /// Name of the state group
        /// (speeds up the search for the state transition storyboard).
        /// </param>
        /// <param name="stateName">
        /// State to transition to.
        /// </param>
        /// <returns>
        /// Awaitable task that completes when the transition storyboard completes.
        /// </returns>
        /// <remarks>
        /// If a state transition storyboard is not found - the task
        /// completes immediately.
        /// </remarks>
        public static async Task GoToVisualStateAsync(
            this Control control,
            FrameworkElement visualStatesHost,
            string stateGroupName,
            string stateName)
        {
            var tcs = new TaskCompletionSource<Storyboard>();

            Storyboard storyboard =
                GetStoryboardForVisualState(visualStatesHost, stateGroupName, stateName);

            if (storyboard != null)
            {
                EventHandler<object> eh = null;

                eh = (s, e) =>
                {
                    storyboard.Completed -= eh;
                    tcs.SetResult(storyboard);
                };

                storyboard.Completed += eh;
            }

            VisualStateManager.GoToState(control, stateName, true);

            if (storyboard == null)
            {
                return;
            }

            await tcs.Task;
        } 
        #endregion

        #region GetStoryboardForVisualState()
        /// <summary>
        /// Gets the state transition storyboard for the specified state.
        /// </summary>
        /// <param name="visualStatesHost">
        /// FrameworkElement that defines the visual states
        /// (usually the root of the control's template).
        /// </param>
        /// <param name="stateGroupName">
        /// Name of the state group
        /// (speeds up the search for the state transition storyboard).
        /// </param>
        /// <param name="stateName">
        /// State to transition to.
        /// </param>
        /// <returns>The state transition storyboard.</returns>
        private static Storyboard GetStoryboardForVisualState(
            FrameworkElement visualStatesHost,
            string stateGroupName,
            string stateName)
        {
            Storyboard storyboard = null;

            var stateGroups = VisualStateManager.GetVisualStateGroups(visualStatesHost);
            VisualStateGroup stateGroup = null;

            if (!string.IsNullOrEmpty(stateGroupName))
            {
                stateGroup = stateGroups.FirstOrDefault(g => g.Name == stateGroupName);
            }

            VisualState state = null;

            if (stateGroup != null)
            {
                state = stateGroup.States.FirstOrDefault(s => s.Name == stateName);
            }

            if (state == null)
            {
                foreach (var group in stateGroups)
                {
                    state = group.States.FirstOrDefault(s => s.Name == stateName);

                    if (state != null)
                    {
                        break;
                    }
                }
            }

            if (state != null)
            {
                storyboard = state.Storyboard;
            }

            return storyboard;
        } 
        #endregion
    }
}

这就是我所说的:

await this.GoToVisualStateAsync(_layoutRoot, PopupStatesGroupName, OpenPopupStateName);

其中this是我的InputDialog控件,而_layoutRoot是其template定义的一部分,如下所示:

<Setter
    Property="Template">
    <Setter.Value>
        <ControlTemplate
            TargetType="controls:InputDialog">
            <Grid
                x:Name="LayoutRoot"
                Background="{TemplateBinding BackgroundScreenBrush}">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup
                        x:Name="PopupStates">
                        <VisualState
                            x:Name="OpenPopupState">
                            <Storyboard>
...

提取该可视状态组后,您可以通过获取stateGroup.CurrentState来获取最后设置状态。

答案 2 :(得分:1)

在UWP XAML中,只需命名为VisualStateGroup:

<VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="PopupStates">
                <VisualState x:Name="Mobile">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="0"/>
                    </VisualState.StateTriggers>

你得到的名字是:

PopupStates.CurrentState.Name