/// <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); }
/// <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; }