Governor Technology Blog

23 October 2009 by Administrator

Creating back button functionality in a Rich UI application using the Momento Pattern.

When using the Silverlight Twitter app I've just created I sometimes make a few UI actions and want to be able to go back a few steps much like the back button in a web browser.  This blog post will tell you how I do that. Furthermore, this can be used in quite a few scenarios such as graphic packages or data modelling software where you the ability to go back and tweak changes.

Here, I have to generate a way of storing the state and go back and forward in the Twitter browsing history. To achieve the former we can loosely follow the example of the Memento described in Design Patterns by the Gang of Four.   

How the Memento Pattern works

The idea of the Memento Pattern is to store a representation of the state of the program and then have a capability to revert to that state when required.  

The class whose state you want to save is called the Originator. In this you need  two functions: one called CreateMemento which creates an object that stores the internal data structure and the other called SetState which sets the internal data structure to a particular state.

You also have to create a class called Memento whose data structure matches the internal data structure in the Originator.

Here's the code for the Memento:

    internal class TwitterMemento

    {

        public string Url { get; set; }

        public string SearchText { get; set; }

 

        public TwitterMemento(string url, string searchText)

        {

            this.Url = url;

            this.SearchText = searchText;

        }

    }

 

In the code above the RestfulUrl is the action that retrieves the information from the Twitter API such as http://twitter.com/statuses/friends_timeline.xml  and SearchText is the text in the search box. 

And here is the Code found within the Originator:

        private TwitterMemento CreateMomento()

        {

            return new TwitterMemento(this.restfulUrl, this.searchText.Text);

        }

 

        private void SetState(TwitterMemento momento)

        {

            this.restfulUrl = momento.Url;

            this.searchText.Text = momento.SearchText;

            ExecuteGetCommand(false);

        }

 

Creating the data structure to store the browsing history:

Now I'll be looking how to store the mementos, in Design Patterns' terms this class is known as the Caretaker.

The major design decision was what kind of data collection I should use in order to save the mementos. I thought about a stack but you couldn't go forward again after you popped a few items off the stack, a List<T> was good but it didn't have a mechanism for storing your position in the browsing history.  So to make this work I extended the list to include an internal pointer that keeps track of the position of the list and is used to check that you are not out of bounds.

I also added functions to check if there were Next and Previous items in the list which is useful to enable/disable the next and previous buttons in the UI.

 

    public class History<T> : List<T>

    {

 

        private int historyPointer = -1;

 

        public bool IsPreviousItem()

        {

 

            return historyPointer > 0;

        }

 

        public bool IsNextItem()

        {

            return (this.Count - historyPointer > 1);

        }

 

        public void AddToHistory(T item)

        {

            //Cause below is true when gone back in history then

            //start a new branch which means old branch is irrelevant and discarded

            if (this.Count - historyPointer > 1)

            {

                int itemsToRemoveFrom = historyPointer + 1;

                this.RemoveRange(itemsToRemoveFrom, this.Count - itemsToRemoveFrom);

            }

 

            this.Add(item);

            historyPointer++;

 

        }

 

        public T GetNextItem()

        {

            historyPointer++;

            return this[historyPointer];

        }

 

        public T GetCurrentItem()

        {

            return this[historyPointer];

        }

 

 

        public T GetPreviousItem()

        {

            historyPointer--;

            return this[historyPointer];

        }

    }

 

So in the class you want to add browsing history you add code along the lines of:

 

        //initiate browser history object

        History<TwitterMemento> twitterHistory = new History<TwitterMemento>();

  

        //choose when to add mementos by using....

        twitterHistory.AddToHistory(this.CreateMomento());

 

        //Disable the Next and previous buttons accordingly....

        Previous.IsEnabled = twitterHistory.IsPreviousItem();

        Next.IsEnabled = twitterHistory.IsNextItem();

 

        //Change the state...

        private void Previous_Click(object sender, System.Windows.RoutedEventArgs e)

        {

            this.SetState(twitterHistory.GetPreviousItem());

        }

 

        private void Next_Click(object sender, System.Windows.RoutedEventArgs e)

        {

            this.SetState(twitterHistory.GetNextItem());

        }

I hope this gives you an understanding on how to add browsing history to a UI rich application.

0 comment(s) for “Creating back button functionality in a Rich UI application using the Momento Pattern.”


    Leave comment:


    (not shown)


    (optional - remember http://)