/// <summary>
        /// RevealModeProperty property changed handler.
        /// </summary>
        /// <param name="dependencyObject">ExpandableContentControl that changed its RevealMode.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnRevealModePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            ExpandableContentControl source = (ExpandableContentControl)dependencyObject;
            ExpandDirection          value  = (ExpandDirection)e.NewValue;

            if (value != ExpandDirection.Down &&
                value != ExpandDirection.Left &&
                value != ExpandDirection.Right &&
                value != ExpandDirection.Up)
            {
                // revert to old value
                source.RevealMode = (ExpandDirection)e.OldValue;

                string message = string.Format(
                    CultureInfo.InvariantCulture,
                    AccordionResources.Expander_OnExpandDirectionPropertyChanged_InvalidValue,
                    value);
                throw new ArgumentException(message, "e");
            }

            // set the non-reveal dimension
            source.SetNonRevealDimension();

            // calculate the reveal dimension
            source.SetRevealDimension();
        }
        /// <summary>
        /// PercentageProperty property changed handler.
        /// </summary>
        /// <param name="dependencyObject">Page that changed its Percentage.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnPercentagePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            ExpandableContentControl source = (ExpandableContentControl)dependencyObject;

            source.SetRevealDimension();
            source.InvalidateMeasure();
        }
        /// <summary>
        /// Coerce the percentage property as necessary.
        /// </summary>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <param name="baseValue">The base value.</param>
        /// <returns>The coerced value.</returns>
        private static object CoercePercentageProperty(DependencyObject dependencyObject, object baseValue)
        {
            // This works around a subtle difference between WPF 3 and SL 3,
            // where a value assigned to a dependency property from within the control
            // is considered to be from a local source, and trumps styles/templates from that point forward.
            // This could be worked around in WPF 4.0 with DependencyObject.SetCurrentValue()
            object returnValue = baseValue;
            ExpandableContentControl expandableContentControl = dependencyObject as ExpandableContentControl;

            // This method can be called by a parent control through RecalculatePercentage(double)
            // To know when to coerce and avoid having to do so more than needed, calculatePercentage can have 3 states:
            // Null: Don't corce using internal value, simply return baseValue
            // Double.NAN: Coerce by computing new percentage value based on current target size
            // value: Corece by returning explicit value previously set in RecalculatePercentage(double)
            if (expandableContentControl != null && expandableContentControl.calculatePercentage.HasValue)
            {
                if (double.IsNaN(expandableContentControl.calculatePercentage.Value))
                {
                    returnValue = CalculatePercentage(expandableContentControl, expandableContentControl.TargetSize);
                }
                else
                {
                    returnValue = expandableContentControl.calculatePercentage.Value;
                }

                expandableContentControl.calculatePercentage = null;
            }

            return(returnValue);
        }
        /// <summary>
        /// TargetSizeProperty property changed handler.
        /// </summary>
        /// <param name="dependencyObject">ExpandableContentControl that changed its TargetSize.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnTargetSizePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            ExpandableContentControl source = (ExpandableContentControl)dependencyObject;
            Size value = (Size)e.NewValue;

            // recalculate percentage based on this new targetsize.
            // for instance, percentage was at 1 and width was 100. Now width was changed to 200, this means
            // that the percentage needs to be set to 0.5 so that a reveal animation can be started again.

            // We are essentially trying to re-evaluate the percentage property based on another property having changed,
            // which is exactly what the coerce functionality of dependency properties is for
            source.RecalculatePercentage(double.NaN);
        }
        /// <summary>
        /// Recalculates the percentage based on a new size.
        /// </summary>
        /// <param name="expandableContentControl">The control which is going to be evaluated</param>
        /// <param name="value">The new size used to base percentages on.</param>
        /// <returns>The new percentage value</returns>
        private static double CalculatePercentage(ExpandableContentControl expandableContentControl, Size value)
        {
            double newPercentage = 0.0;

            if (expandableContentControl.ContentSite != null)
            {
                if (expandableContentControl.IsVerticalRevealMode)
                {
                    newPercentage = expandableContentControl.ActualHeight / (double.IsNaN(value.Height) ? expandableContentControl.ContentSite.DesiredSize.Height : value.Height);
                }
                else if (expandableContentControl.IsHorizontalRevealMode)
                {
                    newPercentage = expandableContentControl.ActualWidth / (double.IsNaN(value.Width) ? expandableContentControl.ContentSite.DesiredSize.Width : value.Width);
                }
            }

            return(newPercentage);
        }
Beispiel #6
0
        /// <summary>
        /// ContentTargetSizeProperty property changed handler.
        /// </summary>
        /// <param name="dependencyObject">AccordionItem that changed its ContentTargetSize.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnContentTargetSizePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            AccordionItem source     = (AccordionItem)dependencyObject;
            Size          targetSize = (Size)e.NewValue;

            if (!source.allowedToWriteContentTargetSize)
            {
                // revert to old value
                source.ContentTargetSize = (Size)e.OldValue;

                throw new InvalidOperationException(AccordionResources.AccordionItem_InvalidWriteToContentTargetSize);
            }

            // Pass the value to the expandSite
            // This is done explicitly so an animation action can be scheduled
            // deterministicly.
            ExpandableContentControl expandSite = source.ExpandSite;

            if (expandSite != null && !expandSite.TargetSize.Equals(targetSize))
            {
                expandSite.TargetSize = targetSize;
                if (source.IsSelected)
                {
                    if (source.ParentAccordion != null && source.ParentAccordion.IsResizing)
                    {
                        // if the accordion is resizing, this item should snap immediately
                        expandSite.RecalculatePercentage(1);
                    }
                    else
                    {
                        // otherwise schedule the resize
                        source.Schedule(AccordionAction.Resize);
                    }
                }
            }
        }
        /// <summary>
        /// Recalculates the percentage based on a new size.
        /// </summary>
        /// <param name="expandableContentControl">The control which is going to be evaluated</param>
        /// <param name="value">The new size used to base percentages on.</param>
        /// <returns>The new percentage value</returns>
        private static double CalculatePercentage(ExpandableContentControl expandableContentControl, Size value)
        {
            double newPercentage = 0.0;

            if (expandableContentControl.ContentSite != null)
            {
                if (expandableContentControl.IsVerticalRevealMode)
                {
                    newPercentage = expandableContentControl.ActualHeight / (double.IsNaN(value.Height) ? expandableContentControl.ContentSite.DesiredSize.Height : value.Height);
                }
                else if (expandableContentControl.IsHorizontalRevealMode)
                {
                    newPercentage = expandableContentControl.ActualWidth / (double.IsNaN(value.Width) ? expandableContentControl.ContentSite.DesiredSize.Width : value.Width);
                }
            }

            return newPercentage;
        }