views:

76

answers:

2

Is it possible to have nested visual states. What I mean is if a ParentControl has a ChildControl and both have their own visual states, is it possible by setting the state of the ParentControl to change the state of the ChildControl accordingly.

A: 

You need to call the GoToState method to change the visual state of the child control.

Since you need to call a method you can't use Storyboards in visual state manager of a parent control since these can only animate properties.

Hence you need to write some code in the child control. To monitor the state of the parent and respond appropriately.

There are a number of different ways to do this but the crucial nugget of info is to use the VisualStateManager.GetVisualStateGroups method to find the VisualStateGroup on the parent that you are interested in, then attach to that group's CurrentStateChanging event. Hence code in the Child control can be notified when a state its interested in is being transitioned to by the parent and can call GoToState appropriately against itself.

AnthonyWJones
I was hoping for more declarative approach. This somehow forces me to make changes in the control, every time I use it. I guess the I'll just have to implement a dependency property which does what I need, and then just use it in the parents states.
Petar S
@Petar: Well yes, if you need a more general solution to glue controls together then some external set of objects defined in an attached property would de-couple the controls. However you do it, it doesn't yet exist and you will need to write some code to bring it into existence.
AnthonyWJones
A: 

I'm just going to declare a new dependency property:

    public static readonly DependencyProperty StateProperty = 
        DependencyProperty.Register("State", 
        typeof( string ),                           
        typeof( TextBlockControl ),
        new PropertyMetadata("Top", 
        new PropertyChangedCallback(StateChanged)));

    [Category("DigItOut"), Description("State")]
    public string State
    {
        get
        {
            return this.GetValue(StateProperty).ToString();
        }
        set
        {
            this.SetValue(StateProperty, value);
        }
    }

    private static void StateChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)    
    {
        if (!String.IsNullOrEmpty(args.NewValue.ToString()))
            VisualStateManager.GoToState(sender as TextBlockControl, args.NewValue.ToString(), true);
    }

And then just set it from it's parents state:

<VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="States">
            <VisualState x:Name="Reverse">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="textBlockControl" Storyboard.TargetProperty="(TextBlockControl.State)">
                        <DiscreteObjectKeyFrame KeyTime="00:00:00">
                            <DiscreteObjectKeyFrame.Value>
                                <System:String>Bottom</System:String>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="Straight"/>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

But if I still want control over the use of transitions, then I'll have to find another solution. Probably second property.

Petar S