- xplorerbar_demo.zip
- XPlorerBar_demo
- ZonaTools.XPlorerBar.DemoApp.exe
- ZonaTools.XPlorerBar.dll
- ZonaTools.XPlorerBar.Documentation.chm
- xplorerbar_src.zip
- XPlorerBar_src
- XPlorerBar.DemoApp.sln
- XPlorerBar.DemoApp.suo
- XPlorerBar.DemoApp
- App.xaml
- App.xaml.cs
- Converters
- Extra_BindingMode
- Extra_ThemeManagement
- Images
- codeproject120x60.gif
- Computer16.png
- Copy16.png
- CreateFolder16.png
- Delete16.png
- MailFile16.png
- Move16.png
- MusicOnLine16.png
- MyComputer16.png
- MyDocuments16.png
- MyMusic32.png
- MyNetwork16.png
- MyPictures16.png
- MyPictures32.png
- MyPictures48.png
- NetworkFavorites16.png
- OrderPictures16.png
- PlayAll16.png
- PrintPictures16.png
- PublishFolder16.png
- Rename16.png
- SharedMusic16.png
- ShareFolder16.png
- SlideShow16.png
- MainWindow.xaml
- MainWindow.xaml.cs
- Properties
- Resources
- Images
- Folder16.png
- MyComputer16.png
- NetworkPlaces16.png
- PicturePrint16.png
- PictureTasks32.png
- PictureTasksMono48.png
- PrintsOnline16.png
- SlideShow16.png
- Skins
- XPlorerBar.DemoApp.csproj
- XPlorerBar.Documentation
- Help
- Documentation.chm
- LastBuild.log
- XPlorerBarDocumentationProject.shfb
- XPlorerBar.Library
|
#region [ Copyright © 2008, Zona-Tools, all rights reserved. ]
/*
*
This source code is licensed under the Code Project Open License (CPOL).
Check out http://www.codeproject.com/info/cpol10.aspx for further details.
*
*/
#endregion
#region [ Using namespaces ]
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
#endregion
namespace ZonaTools.XPlorerBar
{
/// <summary>
/// Represents a Decorator element that can provide expandable/collapsible
/// effects to a set of UI elements.
/// </summary>
public class XPandableDecorator : Decorator
{
#region [ Fields ]
//Storyboard used to provide expandable/collapsible effects
private Storyboard _stBoard = null;
#endregion
#region [ Constructor ]
//===========================================================================
/// <summary>
/// Static constructor used to override the dependency properties (if
/// needed) and define the default style for the control.
/// </summary>
//===========================================================================
static XPandableDecorator()
{
//Sets the default value of the 'ClipToBounds' dependency property to 'true'
ClipToBoundsProperty.OverrideMetadata(
typeof(XPandableDecorator), new FrameworkPropertyMetadata(true));
//Sets the default value of the 'Opacity' dependency property to '0.0'
OpacityProperty.OverrideMetadata(
typeof(XPandableDecorator), new FrameworkPropertyMetadata(0.0));
//Sets the default value of the 'Focusable' dependency property to 'false'
FocusableProperty.OverrideMetadata(
typeof(XPandableDecorator), new FrameworkPropertyMetadata(false));
}
#endregion
#region [ Dependency properties ]
#region IsExpanded property
//===========================================================================
/// <summary>
/// Gets or sets a value indicating whether the decorator is expanded.
/// This is a dependency property.
/// </summary>
/// <remarks>
/// The default value is <c>false</c>.
/// </remarks>
//===========================================================================
[Category(XPlorerBar.CATEGORYNAME), Browsable(true)]
public bool IsExpanded
{
get { return (bool)GetValue(XPandableDecorator.IsExpandedProperty); }
set { SetValue(XPandableDecorator.IsExpandedProperty, value); }
}
/// <summary>
/// Identifies the <see cref="IsExpanded"/> dependency property.
/// </summary>
public static readonly DependencyProperty IsExpandedProperty =
DependencyProperty.Register("IsExpanded",
typeof(bool), typeof(XPandableDecorator),
new PropertyMetadata(false, new PropertyChangedCallback(OnIsExpandedChanged)));
/// <summary>
/// Invoked whenever the <c>IsExpanded</c> dependency property value
/// has been updated.
/// </summary>
/// <param name="sender">The <c>DependencyObject</c> on which the property
/// has changed value.</param>
/// <param name="e">Event data that is issued by any event that tracks changes
/// to the effective value of this property. </param>
private static void OnIsExpandedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//Gets the XPandableDecorator instance who sent the event
XPandableDecorator expDecorator = (XPandableDecorator)sender;
//Gets the new value of the 'IsExpanded' DP
bool IsExpandedNewValue = (bool)e.NewValue;
//Creates a new storyboard or stops it if it already exists
if (expDecorator._stBoard == null)
expDecorator._stBoard = new Storyboard();
else
expDecorator._stBoard.Stop(expDecorator);
//Creates a new animation for a double value
DoubleAnimation animation = new DoubleAnimation();
animation.To = (IsExpandedNewValue) ? 1.0 : 0.0;
animation.Duration =
(expDecorator.IsLoaded) ?
TimeSpan.FromMilliseconds(expDecorator.ExpandOrCollapseDuration) :
TimeSpan.FromMilliseconds(0.0);
animation.AccelerationRatio = (IsExpandedNewValue) ? 0.0 : 0.33;
animation.DecelerationRatio = (IsExpandedNewValue) ? 0.33 : 0.0;
animation.FillBehavior = FillBehavior.HoldEnd;
//Links it to the 'AnimationProgress' dependency property
Storyboard.SetTargetProperty(animation, new PropertyPath(AnimationProgressProperty));
//Clears previous animations and adds the new one to the storyboard
expDecorator._stBoard.Children.Clear();
expDecorator._stBoard.Children.Add(animation);
//Starts the storyboard and sets it as controllable
expDecorator._stBoard.Begin(expDecorator, true);
}
#endregion
#region AnimationProgress property
//===========================================================================
/// <summary>
/// Gets or sets a value indicating the progression of the animation (the
/// value goes from 0 to 1). This is a dependency property.
/// </summary>
/// <remarks>
/// The default value is 0 (decorator collapsed).
/// </remarks>
//===========================================================================
[Browsable(false)]
public double AnimationProgress
{
get { return (double)GetValue(XPandableDecorator.AnimationProgressProperty); }
set { SetValue(XPandableDecorator.AnimationProgressProperty, value); }
}
/// <summary>
/// Identifies the <see cref="AnimationProgress"/> dependency property.
/// </summary>
public static readonly DependencyProperty AnimationProgressProperty =
DependencyProperty.Register("AnimationProgress",
typeof(double), typeof(XPandableDecorator),
new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsMeasure,
new PropertyChangedCallback(OnAnimationProgressChanged),
new CoerceValueCallback(CoerceAnimationProgress)));
/// <summary>
/// Invoked whenever the <c>AnimationProgress</c> dependency property value
/// has been updated.
/// </summary>
/// <param name="sender">The <c>DependencyObject</c> on which the property
/// has changed value.</param>
/// <param name="e">Event data that is issued by any event that tracks changes
/// to the effective value of this property. </param>
private static void OnAnimationProgressChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//Gets the XPandableDecorator instance who sent the event
XPandableDecorator expDecorator = (XPandableDecorator)sender;
//Updates the instance Visibility
expDecorator.Visibility =
(expDecorator.AnimationProgress > 0.0) ? Visibility.Visible : Visibility.Hidden;
//Updates the instance Opacity
expDecorator.Opacity = expDecorator.AnimationProgress;
}
/// <summary>
/// Invoked whenever the <c>AnimationProgress</c> dependency property value is
/// being re-evaluated, or coercion is specifically requested.
/// </summary>
/// <param name="sender">Not used here.</param>
/// <param name="value">The new value of the property, prior to any coercion
/// attempt.</param>
/// <returns>The coerced value.</returns>
private static object CoerceAnimationProgress(DependencyObject sender, object value)
{
//Gets the value to coerce
double animationProgress = (double)value;
//Keeps the value between 0 and 1
if (animationProgress < 0.0)
animationProgress = 0.0;
else if (animationProgress > 1.0)
animationProgress = 1.0;
return animationProgress;
}
#endregion
#region ExpandCollapseDuration property
//===========================================================================
/// <summary>
/// Gets or sets the duration (in milliseconds) of the expanding
/// (or collapsing) animation. This is a dependency property.
/// </summary>
/// <remarks>
/// The default value is 1000 milliseconds.
/// </remarks>
//===========================================================================
[Category(XPlorerBar.CATEGORYNAME), Browsable(true)]
public Double ExpandOrCollapseDuration
{
get { return (Double)GetValue(XPandableDecorator.ExpandOrCollapseDurationProperty); }
set { SetValue(XPandableDecorator.ExpandOrCollapseDurationProperty, value); }
}
/// <summary>
/// Identifies the <see cref="ExpandOrCollapseDuration"/> dependency property.
/// </summary>
public static readonly DependencyProperty ExpandOrCollapseDurationProperty =
DependencyProperty.Register("ExpandOrCollapseDuration",
typeof(Double), typeof(XPandableDecorator),
new FrameworkPropertyMetadata(1000.0));
#endregion
#endregion
#region [ Layout process ]
//===========================================================================
/// <summary>
/// Measures the size in layout required for its child element and determines
/// the size for this element.
/// </summary>
/// <param name="availableSize">The available size that this element can give
/// to its child element. Infinity can be specified as a value to indicate
/// that the element will size to whatever content is available.</param>
/// <returns>The size that this element determines it needs during layout,
/// based on its calculations of child element sizes.</returns>
//===========================================================================
protected override Size MeasureOverride(Size availableSize)
{
//Gets the single child of the Border
UIElement singleChild = Child;
//Checks if it exists
if (singleChild != null)
{
//Asks the child how big it wants to be within the available area
singleChild.Measure(availableSize);
//Evaluates the height of the element according to child item desired
//height and the animation progress
double height = singleChild.DesiredSize.Height * AnimationProgress;
//Returns the original width associated with the calculated height
return new Size(availableSize.Width, height);
}
return new Size();
}
//===========================================================================
/// <summary>
/// Positions child elements and determines a size for this element.
/// </summary>
/// <param name="arrangeSize">The final area within the parent this
/// element should use to arrange itself and its children.</param>
/// <returns>The actual size used.</returns>
//===========================================================================
protected override Size ArrangeOverride(Size arrangeSize)
{
//Gets the single child of the Border
UIElement singleChild = Child;
//Checks if it exists
if (singleChild != null)
{
//Calculates the y-coordinate of the top left corner of the child
double y = singleChild.DesiredSize.Height * (AnimationProgress - 1.0);
//Tells the single child its location and size
singleChild.Arrange(new Rect(new Point(0.0, y),
new Size(arrangeSize.Width, singleChild.DesiredSize.Height)));
//Returns the original size
return arrangeSize;
}
return new Size();
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I have been developing and managing projects for real-time embedded softwares for eight years. Then, I moved from Paris to the south of France and began to lead a team who was developping Java applications.
My main occupation right now is to continue my journey in the WPF world.
You can check out my blog
here. [
^]