views:

381

answers:

2

Hi all,

Im just starting to get to grips with silverlight 3, coming from ASP.NET and Flex.

I have followed the new navigation tutorial here and read through the authentication and role management tutorials also.

So, i have a main page, which has a frame, inside of the grid, and several views. These are all navigatable and working fine. I see this main page as kind of a master page to my little application i have i mind.

So know I want to have a login.xaml UserControl. This will handle all login and once authenticated I want to navigate to the MainPage, and the use its frame to go from there.

I dont just want to simply use login as a seprate page within my frame as I want the login to use a different grid to the rest of the app, and also to be separate.

So how would I navigate from one user control (Login) to another (Main) ?

I have tried

 private void btnLogin_Click(object sender, RoutedEventArgs e)
    {
        //TO - DO: All the auth work, just want navigation sorted first

        this.Visibility = Visibility.Collapsed;
        App.Current.RootVisual = new MainPage(); 
    }

With no luck. Ive also tried just init'n a new main and setting its Visibility but this of course doesnt work.

Am I even approaching this in the correct way?

Thanks muchly.

Edit - Ok after digging a little further, this looks like an approach that will do what im after, but it does feel a little hackish! Is this the suggested way for siverlight 3? Thanks Again

+2  A: 

What I've usually done is to create a "MainPage.xaml" which is of type System.Windows.Controls.Navigation. That gets assigned to the RootVisual property of my application; it's pretty much empty, except for a navigation frame:

<navigation:Page 
x:Class="Client.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
mc:Ignorable="d" 
d:DesignWidth="400" 
d:DesignHeight="400" MinWidth="700" MinHeight="480"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Title="Main SlideLinc Page">
<Grid x:Name="LayoutRoot">
 <navigation:Frame x:Name="rootFrame" />
</Grid>
</navigation:Page>

Then I use the "rootFrame" navigation frame to handle all my navigation needs, e.g., with these methods from a static NavigationManager class:

    public static void Navigate(string url, Action<Exception, UIElement> callback)
    {
        Navigate(new Uri(url, UriKind.RelativeOrAbsolute), callback);
    }

    public static void Navigate(Uri uri, Action<Exception, UIElement> callback)
    {
        if (rootFrame == null)
        {
            Logger.LogMessage("Can't use navigation, because rootFrame is null");
            ErrorMessageBox.Show(ClientStrings.NavigationFailed);
        }
        else
        {
            NavigatedEventHandler successHandler = null;
            NavigationFailedEventHandler failureHandler = null;
            successHandler = (s, e) =>
                 {
                     rootFrame.Navigated -= successHandler;
                     rootFrame.NavigationFailed -= failureHandler;
                     if (callback != null)
                     {
                         callback(null, e.Content as UIElement);
                     }
                 };
            failureHandler = (s, e) =>
                {
                    rootFrame.Navigated -= successHandler;
                    rootFrame.NavigationFailed -= failureHandler;
                    if (callback != null)
                    {
                        callback(e.Exception, null);
                    }
                };
            rootFrame.Navigated += successHandler;
            rootFrame.NavigationFailed += failureHandler;
            rootFrame.Navigate(uri);
        }
    }

So in your case, you might use it like:

NavigationManager.Navigate(new Uri("/Login.xaml", UriKind.Relative), null);

Or:

NavigationManager.Navigate(new Uri("/Home.xaml", UriKind.Relative), (error, element) => InitializeElement(element));
Ken Smith
This a great approach, nice and clean.Thanks Ken
Jammin
+2  A: 

There are 3 types of containers in SL3

  1. Pages (Views)
  2. UserControls
  3. ChildWindows (Popups)

Do not swap UserControls, its a bad idea, it basically means clearing the "MainPage" content and Adding a new UserControl. By doing ths you lose the Back/Forth behavior of the browser since the URL never changes, thats not how the Navigation Framework was designed, you rather swap Pages (views) do this by using the NavigationService.

private void btnLogin_Click(object sender, RoutedEventArgs e)
    {
        //TO - DO: All the auth work, just want navigation sorted first

        NavigationService.Navigate(new Uri("/HomePage.xaml", UriKind.Relative));
    }

Now HomePage.xaml is a Page (not a UserControl), on Startup your default load page for the NavigationFrame should be your login page.

UserControls are meant to be re-usable functionality that can be deployed on multiple pages.

Neil