/// <summary>
 /// Called when the size of the control changes.
 /// </summary>
 /// <param name="sender">The sender.</param>
 /// <param name="e">The <see cref="System.Windows.SizeChangedEventArgs"/>
 /// instance containing the event data.</param>
 private void OnHeaderSizeChanged(object sender, SizeChangedEventArgs e)
 {
     // allow the parent to reschedule a layout pass.
     if (ParentAccordion != null)
     {
         ParentAccordion.OnHeaderSizeChange(this);
     }
 }
        /// <summary>
        /// Called when a storyboard finishes.
        /// </summary>
        /// <param name="sender">The AccordionItem that finished a storyboard.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing
        /// the event data.</param>
        /// <remarks>AccordionItem is required to make this call.</remarks>
        private void OnStoryboardFinished(object sender, EventArgs e)
        {
            _isBusyWithAction = false;

            if (ParentAccordion != null)
            {
                ParentAccordion.OnActionFinish(this);
            }
        }
        /// <summary>
        /// Schedules the specified action.
        /// </summary>
        /// <param name="action">The action to be performed.</param>
        private void Schedule(AccordionAction action)
        {
#if SILVERLIGHT
            if (DesignerProperties.GetIsInDesignMode(this) && ExpandSite != null)
            {
                switch (action)
                {
                case AccordionAction.None:
                    break;

                case AccordionAction.Collapse:
                    ExpandSite.Percentage = 0;
                    break;

                case AccordionAction.Expand:
                case AccordionAction.Resize:
                    ExpandSite.Percentage = 1;
                    break;

                default:
                    throw new ArgumentOutOfRangeException("action");
                }
                return;
            }
#endif

            ScheduledAction = action;

            if (ParentAccordion == null)
            {
                // no parentaccordion to notify, so just execute.
                StartAction();
            }
            else
            {
                bool directExecute = ParentAccordion.ScheduleAction(this, action);
                if (directExecute)
                {
                    StartAction();
                }
            }
        }
        /// <summary>
        /// Schedules the specified action.
        /// </summary>
        /// <param name="action">The action to be performed.</param>
        private async void Schedule(AccordionAction action)
        {
            if (Windows.ApplicationModel.DesignMode.DesignModeEnabled && ExpandSite != null)
            {
                switch (action)
                {
                case AccordionAction.None:
                    break;

                case AccordionAction.Collapse:
                    ExpandSite.Percentage = 0;
                    break;

                case AccordionAction.Expand:
                case AccordionAction.Resize:
                    ExpandSite.Percentage = 1;
                    break;

                default:
                    throw new ArgumentOutOfRangeException("action");
                }
                return;
            }

            ScheduledAction = action;

            if (ParentAccordion == null)
            {
                // no parentaccordion to notify, so just execute.
                StartAction();
            }
            else
            {
                bool directExecute = await ParentAccordion.ScheduleAction(this, action);

                if (directExecute)
                {
                    StartAction();
                }
            }
        }
        /// <summary>
        /// Starts an action, such as resize, collapse or expand.
        /// </summary>
        internal virtual void StartAction()
        {
            if (ScheduledAction == AccordionAction.None)
            {
                throw new InvalidOperationException(Properties.Resources.AccordionItem_StartAction_InvalidCall);
            }
            Action layoutAction;

            switch (ScheduledAction)
            {
            case AccordionAction.Collapse:
                layoutAction = () =>
                {
                    VisualStateManager.GoToState(this, VisualStates.StateExpanded, false);
                    // We only want to notify the parent that this action is finished when we are done with
                    // the state transition. In SL this is done through OnStoryboardFinished, but the same code
                    // in WPF would result in a corrupted state because OnStoryboardFinished gets called more frequently than expected.
                    // In the WPF case, we make the scheduled action synchornous to ensure the transition is properly done.
#if SILVERLIGHT
                    VisualStateManager.GoToState(this, VisualStates.StateCollapsed, true);
#else
                    if (VisualStateManager.GoToState(this, VisualStates.StateCollapsed, true))
                    {
                        ParentAccordion.OnActionFinish(this);
                    }
#endif
                };
                break;

            case AccordionAction.Expand:
                layoutAction = () =>
                {
                    VisualStateManager.GoToState(this, VisualStates.StateCollapsed, false);
#if SILVERLIGHT
                    VisualStateManager.GoToState(this, VisualStates.StateExpanded, true);
#else
                    if (VisualStateManager.GoToState(this, VisualStates.StateExpanded, true))
                    {
                        ParentAccordion.OnActionFinish(this);
                    }
#endif
                };
                break;

            case AccordionAction.Resize:
                layoutAction = () =>
                {
                    // trigger ExpandedState to run again, by quickly moving to collapsed.
                    // the effect is not noticeable because no layout pass is done.
                    VisualStateManager.GoToState(this, VisualStates.StateExpanded, false);
                    VisualStateManager.GoToState(this, VisualStates.StateCollapsed, false);
#if SILVERLIGHT
                    VisualStateManager.GoToState(this, VisualStates.StateExpanded, true);
#else
                    if (VisualStateManager.GoToState(this, VisualStates.StateExpanded, true))
                    {
                        ParentAccordion.OnActionFinish(this);
                    }
#endif
                };
                break;

            default:
            {
                string message = string.Format(
                    CultureInfo.InvariantCulture,
                    Properties.Resources.AccordionItem_StartAction_InvalidAction,
                    ScheduledAction);

                throw new NotSupportedException(message);
            }
            }

            ScheduledAction = AccordionAction.None;
            layoutAction();
        }