2

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

var currentState = VisualStateManager.GetVisualStateGroups(ContainerGrid);

然而,curentState 似乎什么也没得到。我究竟做错了什么?

4

3 回答 3

2

我发现这个答案对我来说效果更好,因为我不需要任何外部的东西:Silverlight: VisualStateManager.GetVisualStateGroups 不需要,我怎样才能得到它们?

于 2013-02-05T00:51:52.273 回答
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是其模板的一部分,定义如下:

<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.

于 2013-01-31T19:39:10.583 回答
1

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

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

你得到的名字使用:

PopupStates.CurrentState.Name
于 2015-11-02T14:47:35.730 回答