Welcome to MSDN Blogs Sign in | Join | Help

Added FireFox, Safari, and IE7 support to the Silverlight 2 Paging Demo

With just a little code and some prompting from people on Twitter, I was able to add support for FireFox, Safari, and IE7 to the paging demo that I wrote on http://xmldocs.net/sl2paging.  Basically I added a DispatcherTimer to my page class and every 200ms I check to see if the hash has changed.  It definitely isn't as elegant as the hashChanged event in IE8 but it works cross-browser. Here's how I did it.

  1. I added a DispatcherTimer to my page class.
  2. In the Page Loaded event handler, I start the timer if the browser User Agent does not have MSIE 8 in it.
  3. Each time the timer ticks I compare the last hash value with the current document's hash and if it's different, I navigate to the new page.

Please try it out in any supported browser (IE7, IE8, FireFox, Safari) and tell me if it works for you.  Should I change the polling interval to be greater than 200ms?

Here's the source code on MSDN Code Gallery.

Update

8/5/2008 - I wrote too soon. I got a report that this technique is not working on IE7.  I have been running the IE8 beta and I had assumed that since it worked in its IE7 emulation mode, it would work in IE7.  Back to the drawing board...

using System;
using System.Linq;
using System.Windows.Browser;
using System.Windows.Threading;
using System.Windows.Controls;
using System.Windows;

namespace SilverlightPaging
{
    /// <summary>
    /// Page Control
    /// </summary>
    public partial class Page : UserControl
    {
        string m_hash;
        DispatcherTimer m_timer = new DispatcherTimer();
        /// <summary>
        /// Default Constructor
        /// </summary>
        public Page()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Page Loaded handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks>Ingnore the Code Analysis CA1811</remarks>
        private void PageLoaded(object sender, RoutedEventArgs e)
        {
            var info = HtmlPage.BrowserInformation;
            this.DataContext = info;
            
            m_hash = HtmlPage.Window.Eval("document.location.hash") as string;

            if (info.UserAgent.Contains("MSIE 8"))
            {
                HtmlPage.Window.AttachEvent("onhashchange", new EventHandler<HtmlEventArgs>(OnHashChange));
            }
            else
            {
                m_timer.Interval = new TimeSpan(0, 0,0,0, 200);

                m_timer.Tick += new EventHandler(m_timer_Tick);

                m_timer.Start();
            }

            NavigateToTab();
        }

        void m_timer_Tick(object sender, EventArgs e)
        {
            var hash = HtmlPage.Window.Eval("document.location.hash") as string;

            if (hash != m_hash)
            {
                m_hash = hash;

                NavigateToTab();
            }
        }

        private void NavigateToTab()
        {
            var hash = HtmlPage.Window.Eval("document.location.hash") as string;

            if (string.IsNullOrEmpty(hash))
            {
                return;
            }

            hash = hash.Substring(1);

            if (Tabs.SelectedItem != null)
            {
                var selectedItem = Tabs.SelectedItem as TabItem;

                if (string.Compare(selectedItem.Tag.ToString(), hash, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    // Tab is already navigated to
                    return;
                }
            }

            // Get the tab items that have the hash in their Tag attribute
            var selectedItem1 = from item in Tabs.Items.Cast<TabItem>()
                                where string.Compare(item.Tag.ToString(), hash, StringComparison.OrdinalIgnoreCase) == 0
                               select item;

            Tabs.SelectedItem = selectedItem1.First();
        }

        void OnHashChange(object sender, HtmlEventArgs args)
        {
            NavigateToTab();
        }

        /// <summary>
        /// When the tab changes, set the document.location.hash and the document.Title
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks>Ingnore the Code Analysis CA1811</remarks>
        private void TabChanged(object sender, SelectionChangedEventArgs e)
        {
            if (Tabs == null)
            {
                //Tabs will be null during InitializeComponent()
                return;
            }

            TabItem item = Tabs.SelectedItem as TabItem;

            if (item == null)
            {
                return;
            }

            string evalText = string.Format(System.Globalization.CultureInfo.InvariantCulture,
                "document.location.hash=\"{0}\"", item.Tag);

            HtmlPage.Window.Eval(evalText);

            evalText = string.Format(System.Globalization.CultureInfo.InvariantCulture,
                "document.title=\"Silverlight Paging: {0} Tab\"", item.Tag);

            HtmlPage.Window.Eval(evalText);
        }
    }
}
Published Monday, August 04, 2008 11:15 PM by Michael S. Scherotter

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# a-foton &raquo; Added FireFox, Safari, and IE7 support to the Silverlight 2 Paging Demo

# re: Added FireFox, Safari, and IE7 support to the Silverlight 2 Paging Demo

Great work!

But it doesn't work in IE7... The problem is that a change to document.location.hash doesn't add a new entry to the browser history in IE7.

The workaround is to create an iframe through script, and update it when ever you change the location.

This post gives a good roundup of the current states of affairs when it comes to navigation history in AJAX/RIA's:

http://weblogs.asp.net/bleroy/archive/2007/09/07/how-to-build-a-cross-browser-history-management-system.aspx

But again, great work! Love how this solution is all C# (just invoking JavaScript, but no JS files or "stuff" in your HTML).

Cheers,

Jonas :)

Tuesday, August 05, 2008 3:04 AM by follesoe

# re: Added FireFox, Safari, and IE7 support to the Silverlight 2 Paging Demo

Jonas,

Darn!  I'll look into the iframe method and see how to include it in my C# code.

Thanks,

Michael

Tuesday, August 05, 2008 12:50 PM by Michael S. Scherotter

# Silverlight Cream for August 10, 2008 -- #343

Michael Washington with an add-on for SL Desktop already, Mike Snow beginning Terrain tutorials and applying

Sunday, August 10, 2008 9:14 PM by Community Blogs

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker