NavFx Part 3 - At The Interface

Before I move on with my journey of using NavFx to build  VRC3 I want to fulfil a special request and cover how to use the  Interfaces to add NavFx to support to an application built with UserControls instead of the templates or base classes.  For those that have existing applications using the interfaces requires the least changes to code.

NavFx includes four interfaces

  • IApplication
  • IHostPage
  • IPage
  • ITransitor

I am not going to cover ITransitor in this article as it warrants its own article which I will add at some point.

IApplication

IApplication defines only one method that must be implemented GetNavigator.  Why do you need this?

Well if you bundle all of your pages in the application package (.xap) you don't because you can always access the App class and it's properties directly so you could implement whatever you like to provide a singleton instance of the NavFx Navigator to pages in the same package.  However if you are going to seperate some of your pages into Silverlight Libraries and load them dynamically they won't build if you try to do something like App.GetNavigator() because the App class won't be available at build time.

Implementing IApplication in App.xaml.cs provides a known interface to the current application within pages loaded dynamically from libraries.  So with something like this in App.xaml.cs:

public partial class App Application ,NavFx.IApplication 
{
    private NavFx.Navigator navigator;

    #region IApplication Members
    public NavFx.Navigator GetNavigator()
    {
        if(this.navigator == null)
         {
             this.navigator = new NavFx.Navigator();
         }
         return this.navigator;
    } 
    #endregion

    //remainder of code.....
}

With a reference to NavFx in your page library you can do something like this to get a Navigator to work with:

    NavFx.Navigator appNavigator = ((NavFx.IApplication)Application.Current).GetNavigator(); 

IPage

IPage defines two properties Path and IsPinned and must be implemented by any page that you want to register with Navigator.

To add NavFx support to an existing or new UserControl simply add , IPage to the end of the class declaration in the code behind file and implement the interface something like this:

public partial class Page: UserControl, NavFx.IPage 
{
    public Page()
    {
         InitializeComponent();
    } 
   
    #region IPage members
    public string Path
    {
        get
        {
             //return "Page";
            return this.GetType().Name;
        }
    } 

    public bool IsPinned
    {
        get{ return false;}
        set{ throw(new NotImplementedException());}
    }

    #endregion
}

Path must return a unique string representing a key for referencing the page.  In the example I have commented out a string literal return value and returned the name of the class implementing the page.  This is what the PageBase does provided by NavFx and works fine for a flat heirarchy of pages where the naming convention is suitable for use as a key.

With the page in the application package you can register it with something like this in your Application_Startup handler

Page page = new Page(); 
this.GetNavigator().RegisterPage(page);

Then navigate to it like this (of course you are free to create constants for the page keys).

this.GetNavigator().GoToPage("Page"); 

With the page in an external library, from your application package you can load, register and access the page in one statement like this

this.GetNavigator().GoToPage("Page", false, new Uri(@"MyPageLib.dll", UriKind.Relative)); 

This requires MyPageLib.dll to be in the same folder as the .xap file.

IHostPage

IHostPage implements IPage so the above section applies to pages that implement IHostPage.  This interface is intended for pages that host pages.  For example a page that provides a menu or some other navigation feature would implement IHostPage and include a container of some sort where IPage instances would be displayed, perhaps a StackPanel.  IHostPage defines a Navigator property and a SetContent method.

Navigator should simply be a get/set property it is set to this when the IHostPage is passed to Navigator.RegisterPage so an automatic property is perfect for the implementation of this

public NavFX.Navigator Navigator{get; set ;} 

SetContent was added when I discovered that the Content property of a ContentControl is protected and can only be set by subclasses.  As I started using NavFx myself I found it useful to create a Shell page, basically an empty UserControl and started out looking to set the Content property in my SimpleTransitor implementation of ITransitor.  Then it occured to me the right thing to do is leave it up to the host page where it displays a guest page and added the SetContent method.  In the HostPage implementation included in NavFx SetContent simply sets this.Content to whatever is passed, but there are other possibilities.  Assume you have a UserControl that implements IHostPage and includes a StackPanel names contentPanel the implementation of SetContent might look like this.

public void SetContent(IPage page) 
{
    this.contentPanel.Children.Clear();
    this.contentPanel.Children.Add(page);
}

There it is, these three very lightweight interfaces will allow you to use the full power of NavFx in your applications with only a little effort.  For existing applications this means minimal code changes for a lot of benefit IMHO.

All my examples are in C# because that is what I work with, but if you are using VB and you are not sure how to transpose these examples just let me know in a comment and I will provide an sample.

 

Print | posted @ Wednesday, July 02, 2008 8:31 PM

Comments on this entry:

Gravatar # re: NavFx Part 3 - At The Interface
by Mike Hanson at 7/3/2008 7:41 AM

Apologies about the formatting when first posted. Subtext doesn't seem to like pasting formatted code in the editor.
  
Gravatar # re: NavFx Part 3 - At The Interface
by Genarg at 7/5/2008 12:17 AM

Hi, everytime i try to create a proyect using your template, it tells me "ComputaGuru.Web.UI.Silverlight.NavFx.dll can't be found inside the templates of the proyect" or something like that. What am i doing wrong? Thanks.
  
Gravatar # re: NavFx Part 3 - At The Interface
by Mike Hanson at 7/5/2008 8:24 AM

I think you may have an old version of the template, I removed my personal namespace from the project and it should now only be looking for NavFx.dll. I will try testing them again, but in the mean time you might want to try downloading the latest templates
  
Gravatar # re: NavFx Part 3 - At The Interface
by Mike Hanson at 7/5/2008 10:07 AM

I found some the problem. I modified the template manually instead of exporting again and forgot to change the template file. Sorted now and a new template release has been uploaded to http://www.codeplex.com/NavFx/Release/ProjectReleases.aspx?ReleaseId=15035
  
Gravatar # re: NavFx Part 3 - At The Interface
by Genarg at 7/5/2008 3:38 PM

Now works great! I will tell you how its goes latter. Cheers!
  
Gravatar # re: NavFx Part 3 - At The Interface
by Justin-Josef Angel [MVP] at 7/6/2008 1:11 AM

Hi Mike,

Awesome work!!!
really cool stuff.
It looks like you've built a much needed wonderful extensible framework.

I'll be sure to build a demo app with this real soon and give you more concrete feedback.

In the meanwhile, consider changing this syntax:
((NavFx.IApplication)Application.Current).GetNavigator();
To an extension method on Application. So the syntax becomes:
Application.Current.GetNavigator().
which will return null if there's no navigator or if the Application.Current doesn't implement IApplication.

Great work,
Justin
  
Gravatar # re: NavFx Part 3 - At The Interface
by Mike Hanson at 7/6/2008 8:14 PM

Good idea, extension methods are one of those things I keep forgetting exist, will certainly implement that one.
  
Gravatar # re: NavFx Part 3 - At The Interface
by Fallon Massey at 7/8/2008 5:33 AM

Mike, it was easier for me to just use your standard markup, instead of all the changes.

We have tools to create the xaml & xaml.cs, and I can specify namespaces, inheritance, etc, so it's not really a big deal, and certainly easier than all the code mods.

By next week I should really have more time to dedicate to this. Take care for now.
  
Gravatar # re: NavFx Part 3 - At The Interface
by Shemesh at 7/17/2008 4:53 PM

what if i want more the one HostPage?
  
Gravatar # re: NavFx Part 3 - At The Interface
by Mike Hanson at 7/17/2008 5:46 PM

That is no problem. You can have nested HostPages.

The way I have structured my applications using NavFx is to create a Shell page that is a HostPage then this acts as the main container for all other pages. Within this I provide the basic navigation and have a ContentPanel which is the target for all my navigation.

But there is nothing stopping you from having multiple content panels and targeting them with different navigation actions.

I am currently writing my 4th article that talks about structuring applications, I hope to get this out with an updated Demo this weekend.
  
Gravatar # re: NavFx Part 3 - At The Interface
by Mike Hanson at 7/17/2008 5:49 PM

I should have added you can load HostPages into the content panels mentioned. In my 5th article I plan to demonstrate the implementation of a Wizard using NavFx which does exactly that. The wizard is a HostPage that dynamically loads it's pages.
  
Gravatar # re: NavFx Part 3 - At The Interface
by Shemesh at 7/20/2008 9:14 AM

let me re-phrase my question.
i know i can have more then one HostPage in the app`.
but how do i navigate the two different HostPage(s)?

calling this: Navigator nav = (NavFx.Application.Current as App).GetNavigator();
then: nav.GoToPage("First");

but how the Navigator will know to which HostPage to refer?
  
Gravatar # re: NavFx Part 3 - At The Interface
by Mike Hanson at 7/20/2008 12:54 PM

Sorry I didn't understand your question.

I have just posted an article that I think will answer you question. There are some formatting issues thanks to the editor changing it on post, I am working on these now but it is still readable.

I think what you are asking is how will NavFx know where to display a page. This is controlled by the Transitor. If you are using the SimpleTransitor provided with NavFx then you need to set the Target property of the Transitor. Both the new article and the updated Demo application provide examples of how to structure your application and pages and how to set the Target property.

If you still have questions after checking these out let me know.
  
Gravatar # re: NavFx Part 3 - At The Interface
by software developer at 8/27/2009 3:08 PM

Cool,

I read about interfaces many time but it was the first time that I actually understood the concept

Thanks for bringing this up
  

Your comment:

Title:
Name:
Email:
Website:
 
Italic Underline Blockquote Hyperlink
 
 
Please add 2 and 3 and type the answer here: