3

I have a DataTemplate. It has two visual states - Expanded, Collapsed. I added 2 GoToStateAction-s. The first one goes to the Expanded state when a data context property becomes True, and the second one goes to the Collapsed state when that same property becomes False.

A Checkbox is part of the template and bound to that property. So when the Checkbox gets checked/unchecked the necessary transition happens.

But none of the actions are applied on startup. The Checkbox is Checked but the Expanded visual state is not applied.

Is it possible using the Visual State Manager to have all items loaded with states applied according to the property values?

arconaut
  • 3,227
  • 2
  • 27
  • 36
  • I am having this problem as well, did you ever find a solution? – PatrickV Apr 06 '12 at 13:36
  • For posterity, the following was suggested to work in a deleted answer: http://stackoverflow.com/questions/10076732/displaystatebehavior-not-initially-applying-state-transition-in-listbox-item-tem/10078474#10078474 – Scott Ritchie May 07 '14 at 12:08

3 Answers3

2

It sounds like you need to override OnApplyTemplate and call VisualStateManager.GoToState(). What happened was your control was loaded, data binding occurred, and then the template was applied. Thus the template is in the base state because nothing told it to perform a state transition. You might be able to do it all from XAML by hooking into the loaded event, but you might find it to be flaky.

Mike Post
  • 6,355
  • 3
  • 38
  • 48
0

You just need to add another GoToStateAction that sets the desired states upon the OnLoad event firing.

update

I haven't tested this, but I think you could use a custom TargetedTriggerAction that derives from GoToStateAction:

public class GoToStateIfCheckedAction : GoToStateAction
{
    protected override void Invoke(object parameter)
    {
        var toggleButton = Target as ToggleButton;
        if (toggleButton != null && (!toggleButton.IsChecked.HasValue || !toggleButton.IsChecked.Value))
        {
            // if the Target is a ToggleButton, and it is in an indeterminate or unchecked state, don't invoke
            return;
        }

        // if the Target is not a ToggleButton, or if the ToggleButton is checked, go ahead and invoke the action
        base.Invoke(parameter);
    }
}

When attached to a ToggleButton, such as CheckBox, this action will only be executed when IsChecked == true.

You could trigger this from the OnLoad event and it will go to the state if the box is checked, or do nothing if unchecked.

Community
  • 1
  • 1
Jay
  • 56,361
  • 10
  • 99
  • 123
  • The problem is that I can't tell what state needs to be set upon OnLoad. It depends on the value of the data context property. Or am I missing something obvious here? – arconaut Aug 06 '10 at 14:18
  • @arconaut No, I don't think you're missing something obvious. The problem is that the behaviour can only be triggered by an event. So the checkbox is not always in the same state on startup? – Jay Aug 06 '10 at 14:24
  • No, it's not. It's bound to data, and the items of that data may have properties having different values – arconaut Aug 06 '10 at 14:41
0

I have a similar problem that a binded visual state is not applied on view load:

<core:PropertyChangedTrigger Binding="{Binding State}">
    <core:GoToStateAction StateName="{Binding State}" />
</core:PropertyChangedTrigger>

As I am using MVVM architecture I cannot override the view's OnApplyTemplate as the view cannot 'see' the ViewModel.

Finally, I found that EventTrigger helps and I want to share it with you:

<interactivity:Interaction.Triggers>
    <interactivity:EventTrigger>
        <core:GoToStateAction StateName="{Binding State}" />
    </interactivity:EventTrigger>
    <core:PropertyChangedTrigger Binding="{Binding State}">
        <core:GoToStateAction StateName="{Binding State}" />
    </core:PropertyChangedTrigger>
</interactivity:Interaction.Triggers>

where xmlns:interactivity="http://schemas.microsoft.com/expression/2010/interactivity"

J Pollack
  • 2,788
  • 3
  • 29
  • 43
  • It is funny to read a post, find a misleading statement like 'a View cannot see ViewModel in MVVM'. Then trying out the suggestion which just works in your situation as well! Then want to give a up-vote, will discover that it was your post 6 months ago :D #madness# – J Pollack Nov 22 '16 at 14:01