<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Silverlight &#124; WPF &#124; Microsoft.Net &#187; Navigation</title>
	<atom:link href="http://joel.neubeck.net/tag/navigation/feed/" rel="self" type="application/rss+xml" />
	<link>http://joel.neubeck.net</link>
	<description>Simplifing structure without changing results</description>
	<lastBuildDate>Fri, 01 Apr 2011 21:34:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Navigation Transitions with WriteableBitmap</title>
		<link>http://joel.neubeck.net/2009/08/navigation-transitions-with-writeablebitmap/</link>
		<comments>http://joel.neubeck.net/2009/08/navigation-transitions-with-writeablebitmap/#comments</comments>
		<pubDate>Fri, 14 Aug 2009 17:16:03 +0000</pubDate>
		<dc:creator>joel</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Easing]]></category>
		<category><![CDATA[HyperlinkButton]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Silverlight 3]]></category>
		<category><![CDATA[WriteableBitmap]]></category>

		<guid isPermaLink="false">http://joel.neubeck.net/2009/08/navigation-transitions-with-writeablebitmap/</guid>
		<description><![CDATA[If you have not had a chance to play with Navigation Frames in Silverlight they are very cool, they give developers the ability to navigate between &#34;Page&#34; within a single Silverlight Solution.&#160; The first time I used them I could believe how easy it was to implement.&#160; You simply add a few pages to your [...]]]></description>
			<content:encoded><![CDATA[<p>If you have not had a chance to play with Navigation Frames in Silverlight they are very cool, they give developers the ability to navigate between &quot;Page&quot; within a single Silverlight Solution.&#160; The first time I used them I could believe how easy it was to implement.&#160; You simply add a few pages to your solution, drop a Navigation:Frame on to your MainPage.xaml UserControl and define some UriMappers.</p>
<p>One thing that i thought was missing was the ability to&#160; create nice looking transitions between pages as they are loaded into a frame.&#160; Recently I voiced my complaint to a coworker (the infamous Steve Saxon &#8211; <a href="http://twitter.com/xmlguy" target="_blank">@xmlguy</a>) and he had the great idea of using a WritableBitmap to capture the current and next page within the Frame, than animating the images.&#160; Here is the solution I arrived at.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
</pre></td><td class="code"><pre class="c-sharp" style="font-family:monospace;">using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
&nbsp;
namespace NavigationTransition
{
    public partial class MainPage : UserControl
    {
        private HyperlinkButton _lastClicked;
        private bool _isNavigating = false;
        private readonly Image _imgLast = new Image();
        private readonly Image _imgNext = new Image();
        private Storyboard _sb = new Storyboard();
&nbsp;
        public MainPage()
        {
            InitializeComponent();
        }
&nbsp;
        void SbCompleted(object sender, EventArgs e)
        {
            Panel panel = ContentFrame.Parent as Panel;
            panel.Children.Remove(_imgLast);
            panel.Children.Remove(_imgNext);
            ContentFrame.Visibility = Visibility.Visible;
            _sb.Stop();
            _isNavigating = false;
        }
&nbsp;
        private void ContentFrameNavigated(object sender, NavigationEventArgs e)
        {
            ContentFrame.Navigated -= ContentFrameNavigated;
            Panel panel = ContentFrame.Parent as Panel;
            panel.UpdateLayout();
&nbsp;
            WriteableBitmap bitmapN = new WriteableBitmap(ContentFrame, new TranslateTransform());
            _imgNext.Source = bitmapN;
            TranslateTransform ttNext = new TranslateTransform();
&nbsp;
            _imgNext.RenderTransform = ttNext;
            panel.Children.Add(_imgNext);
&nbsp;
            _sb.Children.Add(CreateDoubleAnimation(ttNext, &amp;quot;X&amp;quot;, -bitmapN.PixelWidth, 0, true)); 
            ContentFrame.Visibility = Visibility.Collapsed;
&nbsp;
            _sb.Begin();
&nbsp;
        }
&nbsp;
&nbsp;
        private void Nav_Click(object sender, RoutedEventArgs e)
        {
            _lastClicked = (HyperlinkButton)sender;
            if (ContentFrame.Source.ToString() != _lastClicked.Tag.ToString() &amp;amp;&amp;amp; !_isNavigating)
            {
                _sb = new Storyboard();
                _sb.Completed += SbCompleted;
&nbsp;
                Panel panel = ContentFrame.Parent as Panel;
&nbsp;
                WriteableBitmap bitmapL = new WriteableBitmap(ContentFrame, new TranslateTransform());
                _imgLast.Source = bitmapL;
                TranslateTransform ttLast = new TranslateTransform();
                _imgLast.RenderTransform = ttLast;
                if (panel != null) panel.Children.Add(_imgLast);
&nbsp;
                ContentFrame.Navigated += ContentFrameNavigated;
                ContentFrame.Navigate(new Uri(_lastClicked.Tag.ToString(), UriKind.Relative));
&nbsp;
                _sb.Children.Add(CreateDoubleAnimation(ttLast, &amp;quot;X&amp;quot;, 0, bitmapL.PixelWidth, true));
&nbsp;
                _isNavigating = true;
            }  
        }
        private static DoubleAnimation CreateDoubleAnimation(DependencyObject element, 
              string property, double from, double to, bool addEasing)
        {
            DoubleAnimation da = new DoubleAnimation();
            da.To = to;
            da.From = from;
            if (addEasing)
                da.EasingFunction = new PowerEase() { EasingMode = EasingMode.EaseOut, Power = 3 };
&nbsp;
&nbsp;
            Storyboard.SetTargetProperty(da, new PropertyPath(property));
            Storyboard.SetTarget(da, element);
            return da;
        }
        // If an error occurs during navigation, show an error window
        private void ContentFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            e.Handled = true;
            ChildWindow errorWin = new ErrorWindow(e.Uri);
            errorWin.Show();
        }
    }
}</pre></td></tr></table></div>

<p>One of the things I found necessary was to delay the navigation so that I could capture a bitmap of the current frame.&#160; The way I intersected the navigation&#160; was to attach a Click event handler to my HyperlinkButton and then store the Uri in the Tag property.&#160; With a little more effort you could make this into a Behavior or even add a few additional types of transitions.</p>
<p>&#160; <br style="clear: both" /><iframe height="300" src="/wp-content/uploads/2009/08/NavigationTransition/" width="500"></iframe></p>
<p>  <br style="clear: both" />Code: <a onclick="javascript:pageTracker._trackPageview(&#39;/code/NavigationTransition.zip&#39;); " href="/wp-content/uploads/2009/08/NavigationTransition/NavigationTransition.zip">NavigationTransition.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://joel.neubeck.net/2009/08/navigation-transitions-with-writeablebitmap/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

