wpfxamltriggersvisualstatemanager

How, if at all, can you invoke a VisualStateManager.GotToState from a Style Trigger IsSelected property


I have VisualStateManager.VisualStateGroups defined as follows:

            <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="PopupStates">
                <VisualState x:Name="PopupClosed">
                    <Storyboard>
                        <BooleanAnimationUsingKeyFrames Storyboard.TargetName="ContextPopup"
                                            Storyboard.TargetProperty="IsOpen">
                            <DiscreteBooleanKeyFrame KeyTime="0:0:0.25"
                                       Value="False" />
                        </BooleanAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames
                                        Storyboard.TargetName="rootGrid"
                                        Storyboard.TargetProperty="(Panel.Background)">
                            <DiscreteObjectKeyFrame KeyTime="0:0:0.25" Value="{DynamicResource BrushIconComboBox_Popup_Closed_Background}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="PopupOpen">
                    <Storyboard>
                        <BooleanAnimationUsingKeyFrames Storyboard.TargetName="ContextPopup"
                                            Storyboard.TargetProperty="IsOpen">
                            <DiscreteBooleanKeyFrame KeyTime="0:0:0.25"
                                       Value="True" />
                        </BooleanAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames
                                        Storyboard.TargetName="rootGrid"
                                        Storyboard.TargetProperty="(Panel.Background)">
                            <DiscreteObjectKeyFrame KeyTime="0:0:0.25" Value="{DynamicResource BrushIconComboBox_Popup_Open_Background}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

In a Style declaration, I would like to invoke the VisualStateManager.GoToState "PopupClosed" if a listboxitem is clicked on (i.e. selected via Mouse action). I have not been able to find an example where a VisualStateManager.GoToState can be combined with a Trigger, such as:

     <Style.Triggers>
        <Trigger Property="IsSelected" Value="true">
           ... VisualStateManager.GoToState declaration ....
        </Trigger>
    </Style.Triggers>

Is there a way to do this? Any help is appreciated.


Solution

  • You can't invoke methods from XAML except those methods are event/command handlers (delegates). You must call methods explicitly from a non-XAML context.

    VisualStates are usually handled by the control that defines them. If this is not about a custom control and you need to change the visual state transitioning behavior or triggers, the cleanest way would be to extend the relevant control to implement the state transitioning privately.
    However, using VisualStateManager.GoToElementState allows to transition a control into a visual state externally, for example from an attached ListBoxItem.Selected event handler..

    <ListBox>
      <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
          <EventSetter Event="Selected"
                       Handler="ListBoxItem_Selected" />
        </Style>
      </ListBox.ItemContainerStyle>
    </ListBox>
    
    private void ListBoxItem_Selected(object sender, RoutedEventArgs e)
    {
      var listBoxItem = sender as ListBoxItem;
      var templateChildThatDefinesVisualStateGroups = VisualTreeHelper.GetChild(listBoxItem, 0) as FrameworkElement;
      _ = VisualStateManager.GoToElementState(templateChildThatDefinesVisualStateGroupshild, "PopupClosed", true);
    }