Click here to Skip to main content
15,895,740 members
Articles / Desktop Programming / WPF

Animated WPF Panels

Rate me:
Please Sign up or sign in to vote.
4.96/5 (43 votes)
14 Feb 2011CPOL6 min read 141.6K   8.3K   67  
Adding animation support to existing WPF Panels
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using Bornander.UI.Animations;
using Bornander.UI.Animations.Animators;

namespace Bornander.UI.Test
{
    public partial class GridBackground : Window
    {
        private const int NumberOfRows = 4;
        private const int NumberOfColumns = 4;
        private const double DesiredAspectRatio = 1024.0 / 768.0;

        private readonly Random random = new Random();

        private IDictionary<string, IList<UIElement>> backgrounds = new Dictionary<string, IList<UIElement>>(); 

        public GridBackground()
        {
            InitializeComponent();

            backgroundGrid.SizeChanged += GridBackground_SizeChanged;
            backgroundGrid.Animator = new FractionDistanceAnimator(0.1);

            foreach (string name in new[] { "Jellyfish", "Koala", "Penguins" })
            {
                backgrounds[name] = new List<UIElement>();
                BitmapSource[,] tiles = SplitImage(LoadImage(String.Format(@"Images\{0}.jpg", name)), NumberOfRows, NumberOfColumns);
                for (int row = 0; row < NumberOfRows; ++row)
                {
                    for (int column = 0; column < NumberOfColumns; ++column)
                    {
                        Image image = new Image();
                        image.Source = tiles[row, column];
                        image.SetValue(Grid.RowProperty, row);
                        image.SetValue(Grid.ColumnProperty, column);
                        backgroundGrid.Children.Add(image);
                        backgrounds[name].Add(image);
                    }
                }
            }

            RecalculateOffscreenPoints();

            SizeChanged += (s, e) => RecalculateOffscreenPoints();
        }

        private void RecalculateOffscreenPoints()
        {
            foreach (UIElement element in backgroundGrid.Children)
            {
                element.SetValue(AnimationBase.OverridePositionProperty, GenerateOffscreenPoint());
            }
        }

        private Point GenerateOffscreenPoint()
        {
            double radius = Math.Max(backgroundGrid.ActualWidth, backgroundGrid.ActualHeight) + Math.Max(backgroundGrid.ActualWidth / (double)NumberOfColumns, backgroundGrid.ActualHeight / (double)NumberOfRows);
            return new Point
                (
                (backgroundGrid.ActualWidth / 2.0) + Math.Cos(random.NextDouble() * 2.0 * Math.PI) * radius,
                (backgroundGrid.ActualHeight / 2.0) + Math.Sin(random.NextDouble() * 2.0 * Math.PI) * radius
                );

        }

        void GridBackground_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            double ratio = e.NewSize.Width / e.NewSize.Height;
            if (ratio != DesiredAspectRatio)
            {
                backgroundGrid.Height = e.NewSize.Width / DesiredAspectRatio;
            }

        }

        private static BitmapSource LoadImage(string filename)
        {
            BitmapImage image = new BitmapImage();
            image.BeginInit();
            image.UriSource = new Uri(filename, UriKind.RelativeOrAbsolute);
            image.EndInit();

            return image;
        }

        private static BitmapSource[,] SplitImage(BitmapSource source, int rows, int columns)
        {
            BitmapSource[,] result = new BitmapSource[rows, columns];

            int width = (int)(source.Width / columns);
            int height = (int)(source.Height / rows);

            for (int row = 0; row < rows; ++row)
            {
                for(int column = 0; column < columns; ++column)
                {
                    result[row, column] = new CroppedBitmap(source, new Int32Rect(column * width, row * height, width, height));  
                }
            }

            return result;
        }

        private void ToggleBackground(string name)
        {
            foreach (UIElement element in backgroundGrid.Children)
            {
                element.SetValue(AnimationBase.OverrideArrangeProperty, true);
            }

            foreach (UIElement element in backgrounds[name])
            {
                element.SetValue(AnimationBase.OverrideArrangeProperty, false);
            }
        }

        private void Jellyfish_Click(object sender, RoutedEventArgs e)
        {

            ToggleBackground("Jellyfish");
        }

        private void Koala_Click(object sender, RoutedEventArgs e)
        {
            ToggleBackground("Koala");
        }
        
        private void Penguins_Click(object sender, RoutedEventArgs e)
        {
            ToggleBackground("Penguins");
        }
    }
}

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Sweden Sweden
Article videos
Oakmead Apps Android Games

21 Feb 2014: Best VB.NET Article of January 2014 - Second Prize
18 Oct 2013: Best VB.NET article of September 2013
23 Jun 2012: Best C++ article of May 2012
20 Apr 2012: Best VB.NET article of March 2012
22 Feb 2010: Best overall article of January 2010
22 Feb 2010: Best C# article of January 2010

Comments and Discussions