VisualStateManager does not support TreeViewItem

Feb 17, 2009 at 9:44 PM
I ran into this when trying to use the resource dictionaries in the WPF Themes CodePlex project. These were converted from Silverlight and make use of the VisualStateManager. Unfortunately the TreeViewItem is not recognized by the VSM and thus doesn't have a selected state.

In case anyone stumbles upon this, you can work around it by creating a class TreeViewItemBehavior and registering it at application startup by calling VisualStateBehavior.RegisterBehavior.

    public class TreeViewItemBehavior : ControlBehavior
    {
        
        // Methods
        protected override void OnAttach( Control control )
        {
            base.OnAttach( control );
            TreeViewItem instance = (TreeViewItem)control;
            Type targetType = typeof( TreeViewItem );
            VisualStateBehavior.AddValueChanged( UIElement.IsMouseOverProperty, targetType, instance, new EventHandler( this.UpdateStateHandler ) );
            VisualStateBehavior.AddValueChanged( TreeViewItem.IsSelectedProperty, targetType, instance, new EventHandler( this.UpdateStateHandler ) );
        }

        protected override void OnDetach( Control control )
        {
            base.OnDetach( control );
            TreeViewItem instance = (TreeViewItem)control;
            Type targetType = typeof( TreeViewItem );
            VisualStateBehavior.RemoveValueChanged( UIElement.IsMouseOverProperty, targetType, instance, new EventHandler( this.UpdateStateHandler ) );
            VisualStateBehavior.RemoveValueChanged( TreeViewItem.IsSelectedProperty, targetType, instance, new EventHandler( this.UpdateStateHandler ) );
        }

        protected override void UpdateState( Control control, bool useTransitions )
        {
            TreeViewItem item = (TreeViewItem)control;
            if ( item.IsMouseOver ) {
                VisualStateManager.GoToState( item, "MouseOver", useTransitions );
            }
            else {
                VisualStateManager.GoToState( item, "Normal", useTransitions );
            }
            if ( item.IsSelected ) {
                VisualStateManager.GoToState( item, "Selected", useTransitions );
            }
            else {
                VisualStateManager.GoToState( item, "Unselected", useTransitions );
            }
            base.UpdateState( control, useTransitions );
        }

        /// <summary />
        /// Gets the type of the target.
        /// 
        /// <value />The type of the target.
        protected override Type TargetType
        {
            get
            {
                return typeof( TreeViewItem );
            }
        }

    }