Go to visual states inside a Grid in code behind in Windows Store apps

吃可爱长大的小学妹 提交于 2019-12-18 09:16:34

问题


So my xaml code looks like this -

<Grid x:Name="LayoutRoot">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">

I can't use the GoToVisualState behavior because I need to do some checks before running this animation. So I guess I will have to call something like GoToState or GoToElementState in code behind.

However, ExtendedVisualStateManager doesn't seem to exist in WinRT. I tried using

VisualStateManager.GetCustomVisualStateManager(this.LayoutRoot)

but it always returns null.

Is there any workaround for this?


回答1:


Just figured this out.

First create a helper class just like how we used to use it in Silverlight or Windows Phone (I took this piece of code from here and modified it a little bit so when an element doesn't have any visual state groups attached, it automatically goes search for its parent until it finds any).

public class ExtendedVisualStateManager : VisualStateManager
{
    protected override bool GoToStateCore(Control control, FrameworkElement stateGroupsRoot, string stateName, VisualStateGroup group, VisualState state, bool useTransitions)
    {
        if ((group == null) || (state == null))
        {
            return false;
        }

        if (control == null)
        {
            control = new ContentControl();
        }

        return base.GoToStateCore(control, stateGroupsRoot, stateName, group, state, useTransitions);
    }

    public static bool GoToElementState(FrameworkElement element, string stateName, bool useTransitions)
    {
        var root = FindNearestStatefulFrameworkElement(element);

        var customVisualStateManager = VisualStateManager.GetCustomVisualStateManager(root) as ExtendedVisualStateManager;

        return ((customVisualStateManager != null) && customVisualStateManager.GoToStateInternal(root, stateName, useTransitions));
    }

    private static FrameworkElement FindNearestStatefulFrameworkElement(FrameworkElement element)
    {
        while (element != null && VisualStateManager.GetCustomVisualStateManager(element) == null)
        {
            element = element.Parent as FrameworkElement;
        }

        return element;
    }

    private bool GoToStateInternal(FrameworkElement stateGroupsRoot, string stateName, bool useTransitions)
    {
        VisualStateGroup group;
        VisualState state;

        return (TryGetState(stateGroupsRoot, stateName, out group, out state) && this.GoToStateCore(null, stateGroupsRoot, stateName, group, state, useTransitions));
    }

    private static bool TryGetState(FrameworkElement element, string stateName, out VisualStateGroup group, out VisualState state)
    {
        group = null;
        state = null;

        foreach (VisualStateGroup group2 in VisualStateManager.GetVisualStateGroups(element))
        {
            foreach (VisualState state2 in group2.States)
            {
                if (state2.Name == stateName)
                {
                    group = group2;
                    state = state2;
                    return true;
                }
            }
        }

        return false;
    }
}

Then you will need to manually update the xaml to something like this -

<VisualStateManager.CustomVisualStateManager>
    <common:ExtendedVisualStateManager />
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
    <VisualStateGroup .../>
</VisualStateManager.VisualStateGroups>

I guess the good thing about this solution is that you can still see the visual states in Blend's States tab, for Blend lovers this is just cool.




回答2:


Typically I have a single UpdateVisualState(bool useTransitions) method in my controls that makes all the GoToVisualState() calls. If something can't be animated then I see two options:

  1. Make the change in code behind in my UpdateVisualState() method. The drawback of this solutions is that Blend will not show the change in the visual state editor. I don't personally care though because I rarely use Blend on already integrated designs and this solution is simple.
  2. Create a(n attached) property or behavior that makes the expected change and animate that property from the visual state Storyboard. That's a bit more work, but could keep Blend support in your project.


来源:https://stackoverflow.com/questions/23697204/go-to-visual-states-inside-a-grid-in-code-behind-in-windows-store-apps

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!