Every time when you want to create a pane that can collapse or expand, you have to write either a Storyboard in xaml or some other animation logic. This can be a tedious task and has many pitfalls. Some of them being

  1. Change in width of the pane requires rewiring of the storyboard.
  2. Consistency in the collapse/expand duration of the pane.
  3. Flexibility in changing the pane from vertical to horizontal.

To solve all of these and many more problems that may arise we need to build a custom PaneManager that will do this for us when required.

At first we must create a class in your Silverlight application, lets call it PaneManager, with the following members

public class PaneManager
{

#region Public Members
public TimeSpan Interval { get; set; }
public double Increment { get; set; }
public double MinValue { get; set; }
public double MaxValue { get; set; }
public Grid Grid { get; set; }
public int Index { get; set; }
public GridUnitType GridUnitType { get; set; }
public Orientation Alignment { get; set; }
#endregion

}

Let us go over each member in detail.

  • Interval – This defines the duration to wait between successive calls to make the pane transition.
  • Increment – This is the value by which the pane’s width or height must change.
  • MinValue – This defines the minimum threshold of the pane’s width or height.
  • MaxValue- This defines the maximum threshold of the pane’s width or height.
  • Grid – This is the parent Grid that contains the desired pane.
  • Index – This is the index of the row or column containing the pane.
  • GridUnitType – this is the unit of measurement of the Grid’s row/column.
  • Alignment – This specifies whether the pane transition is to be done on a row or column.

We will also need to add the following members and events to the PaneManager class

#region Private Members
private Storyboard _storyboard = new Storyboard();
#endregion

#region Public Event
public event EventHandler Completed
{

add { _storyboard.Completed += value; }
remove { _storyboard.Completed -= value; }

}
#endregion

We have until now created the basic structure of the PaneManager without adding any functionality as such. To make this class usable, we would be adding two methods Start and Stop to begin and end the storyboard respectively.

In the start method we would be using ObjectAnimationUsingKeyFrames to create Key Frames which will gradually change the pane’s dimensions using the specified interval. This method looks rather long, but is very simple to understand if you know how ObjectAnimationUsingKeyFrames works. The stop method does nothing great, just stops the current storyboard.

public void Start()
{

ObjectAnimationUsingKeyFrames animation = new ObjectAnimationUsingKeyFrames();
TimeSpan start = Interval;
double value = 0;
switch (Alignment)
{

case Orientation.Vertical:

value = Grid.ColumnDefinitions[Index].Width.Value;
Storyboard.SetTargetProperty(_storyboard, new PropertyPath(“ColumnDefinitions[” + Index + “].Width”));
break;

case Orientation.Horizontal:

value = Grid.RowDefinitions[Index].Height.Value;
Storyboard.SetTargetProperty(_storyboard, new PropertyPath(“RowDefinitions[” + Index + “].Height”));
break;

default:

break;

}
while (value + Increment >= MinValue && value + Increment <= MaxValue)
{

value = value + Increment;
animation.KeyFrames.Add(new DiscreteObjectKeyFrame()
{

KeyTime = start,
Value = new GridLength(value, GridUnitType)

});
start += Interval;

}
if (!(value + Increment >= MinValue))

animation.KeyFrames.Add(new DiscreteObjectKeyFrame()
{

KeyTime = start,
Value = new GridLength(MinValue, GridUnitType)

});

else if (!(value + Increment <= MaxValue))

animation.KeyFrames.Add(new DiscreteObjectKeyFrame()
{

KeyTime = start,
Value = new GridLength(MaxValue, GridUnitType)

});

_storyboard.Children.Add(animation);
Storyboard.SetTarget(_storyboard, Grid);
_storyboard.Begin();

}

public void Stop()
{

_storyboard.Stop();

}

You can use this class absolutely anywhere where you want to increment or decrement a row or column of a Grid. The only restrictions is that the container has to be a Grid and that it can be done only through code.

Sample Usage

Here is a code snippet which uses the PaneManager for expand or collapse of a Pane.

PaneManager manager = new PaneManager()
{

Alignment = Orientation.Vertical,
Grid = MainGrid,
Index = 0,
MinValue = 0,
MaxValue = 165,
GridUnitType = System.Windows.GridUnitType.Pixel,
Increment = -5,
Interval = TimeSpan.FromMilliseconds(8)

};

if (isCollapsed)

manager.Increment = manager.Increment * -1;

manager.Completed += new EventHandler((s, args) => { /* Your code */ });
manager.Start();

Next Steps

Many more things can be done so as to make this class more usable, I have listed some of them. If possible, I will write more about them in future posts.

  1. Modify the class to inherit the Storyboard class, so that it can be implemented using xaml
  2. Create a behavior for a UIElement using PaneManager.
  3. Replace the Index and Alignment Properties with a string which will be the property of the Grid( or in this case any UIElement) to animate.
Advertisements

Share your thoughts

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s