none
NullReferenceException while trying to navigate with NavigationService.Navigate(Uri) RRS feed

  • Question

  • Hi

    I'm getting an error while trying to navigate through pages of my winphone Apps

    This is the screen



    Image and video hosting by TinyPic

    This is so strange

    I can't make it works, is there a problem with navigating pages and VB?

    Is there any other way to do this?

    I'm starting thinking about do it with 

    Me.Content = New Page1

    But i don't now if this is a good way to do this


    THANKS A LOT and a happy new year from Spain

    Saturday, January 1, 2011 10:37 AM

Answers

  • I see what's going on now. You aren't navigating to Page1, you're just setting the Content of MainPage to be a new instance of the Page1 class. Since you aren't navigating to Page1, the framework will never hookup the NavigationService it maintains to Page1's NavigationService property.

    You should always go to new pages with the NavigationService. That way when the user presses the Back button, they will go back the previous page (see the Application Certification Requirements for more about proper Back button behavior: http://go.microsoft.com/?linkid=9730558 ). If you want to change what's visible on MainPage once the data from your service comes through, you can do that by updating elements within the page itself (you could define the elements inside the XAML and set their visibility property so that they are hidden, for instance, then change it to visible once ready). But changing the Content property itself is not a good way to do that kind of change since it produces problems like the one you're experiencing and will also produce problems with properly handling a press of the Back button.
    Saturday, January 1, 2011 12:20 PM
  • You should always use UriKind.Relative

    Other than that, it looks like it should work just fine. Trying changing from UriKind.RelativeOrAbsolute to UriKind.Relative and if it's still not working (and not giving any errors), set a breakpoint in the proxy_ComprobarLoginCompleted method and see if it's ever hit and what the values are. If it does throw an exception, post details about the exception it's throwing (e.g. the type of exception, the message, and what line it's throwing it on) and we can try to figure it out from there.
    Saturday, January 1, 2011 12:40 PM
  • No problem.

    ? separates the page you want to go to from the parameters you want to pass.
    & is what you need to use to separate individual parameters. So

        NavigationService.Navigate(New Uri("/Page2.xaml?codigo=" + codigo + "&nombre=" + nombre, UriKind.Relative))

    You should test out what happens if the username and password have an '&' character in them since that could potentially cause a problem (or not; I'm not sure if it properly encodes and decodes special characters or if you need to do that yourself somehow; that's the reason I prefer the Shared class member way - I'm too lazy to figure that out! :) ).
    Saturday, January 1, 2011 1:39 PM

All replies

  • It took me a little while to reproduce this (I had to guess at some things and know next-to-nothing about VB), but I think I know what's going on.

    If your Page1.xaml (specifically the ListBox part) looks something like this:

                <ListBox Name="ListBox1" SelectionChanged="ListBox1_SelectionChanged">  
                    <ListBoxItem IsSelected="True">  
                        <TextBox Name="textBox1" Text="some text" /> 
                    </ListBoxItem> 
                    <ListBoxItem> 
                        <TextBox Text="some other text" /> 
                    </ListBoxItem> 
                </ListBox> 
     

    Then what's happening is that while it's parsing the XAML (i.e. before the page is done being created), it hooks up the SelectionChanged event to the handler method (ListBox1_SelectionChanged in this case; lstCursos_SelectionChanged in your code above) and then hits the ListBoxItem that has IsSelected=true such that it calls ListBox1_SelectionChanged. Because the page hasn't really even been created yet, though, NavigationService has not been created/attached yet by the framework. So it's still null at this point and so you get a NullReferenceException.

    Try changing your code to check for null (Nothing), e.g.:

            If Me.NavigationService IsNot Nothing Then 
                Me.NavigationService.Navigate(uri)  
            End If 
     

    and see if that fixes it.
    Saturday, January 1, 2011 11:43 AM
  • Hi

    I put the code into a Button

     
        Private Sub Button1_Click(ByVal sender As System.ObjectByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click 
            Dim uri As New Uri("MainPage.xaml", UriKind.RelativeOrAbsolute) 
            If NavigationService IsNot Nothing Then 
                Me.NavigationService.Navigate(uri) 
            End If 
     
        End Sub 

    and now it doesn't do anything

    So, NavigationService is Nothing

    If you see the code, i'm on Page1. Page1 is called from MainPage.

    I do it this way

    Imports MyClientWin7.ServiceReference1 
    Imports MD5Core 
    Imports MD5Managed 
    Imports System.Windows 
     
     
    Partial Public Class MainPage 
        Inherits PhoneApplicationPage 
        Public user As String 
        Public pass As String 
        ' Constructor 
        Public Sub New() 
            InitializeComponent() 
            SupportedOrientations = SupportedPageOrientation.Portrait Or SupportedPageOrientation.Landscape 
        End Sub 
     
        Private Sub btnValidar_Click(ByVal sender As System.ObjectByVal e As System.Windows.RoutedEventArgs) Handles btnValidar.Click 
            
            Dim proxy As New Service1Client() 
     
            user = txtUsuario.Text 
            pass = txtPassWord.Password 
            pass = GetHashString(String.Concat(user, pass)) 
     
            AddHandler proxy.ComprobarLoginCompleted, AddressOf proxy_ComprobarLoginCompleted 
            proxy.ComprobarLoginAsync(user, pass) 
     
        End Sub 
        Private Sub proxy_ComprobarLoginCompleted(ByVal sender As ObjectByVal e As ComprobarLoginCompletedEventArgs) 
            If e.Result Then 
            
              Me.Content = New Page1(user) 
            End If 
          
        End Sub 
     
    End Class 
     


    I don't know if i have to do something more than just inserting the navigate(uri) code
    Saturday, January 1, 2011 12:11 PM
  • I see what's going on now. You aren't navigating to Page1, you're just setting the Content of MainPage to be a new instance of the Page1 class. Since you aren't navigating to Page1, the framework will never hookup the NavigationService it maintains to Page1's NavigationService property.

    You should always go to new pages with the NavigationService. That way when the user presses the Back button, they will go back the previous page (see the Application Certification Requirements for more about proper Back button behavior: http://go.microsoft.com/?linkid=9730558 ). If you want to change what's visible on MainPage once the data from your service comes through, you can do that by updating elements within the page itself (you could define the elements inside the XAML and set their visibility property so that they are hidden, for instance, then change it to visible once ready). But changing the Content property itself is not a good way to do that kind of change since it produces problems like the one you're experiencing and will also produce problems with properly handling a press of the Back button.
    Saturday, January 1, 2011 12:20 PM
  • Hi

    Thanks a lot

    And how can i do that?

    This is what i've tried

    Partial Public Class MainPage 
        Inherits PhoneApplicationPage 
        Public user As String 
        Public pass As String 
        ' Constructor 
        Public Sub New() 
            InitializeComponent() 
            SupportedOrientations = SupportedPageOrientation.Portrait Or SupportedPageOrientation.Landscape 
        End Sub 
     
        Private Sub btnValidar_Click(ByVal sender As System.ObjectByVal e As System.Windows.RoutedEventArgs) Handles btnValidar.Click 
            
            Dim proxy As New Service1Client() 
     
            user = txtUsuario.Text 
            pass = txtPassWord.Password 
            pass = GetHashString(String.Concat(user, pass)) 
     
            AddHandler proxy.ComprobarLoginCompleted, AddressOf proxy_ComprobarLoginCompleted 
            proxy.ComprobarLoginAsync(user, pass) 
     
        End Sub 
        Private Sub proxy_ComprobarLoginCompleted(ByVal sender As ObjectByVal e As ComprobarLoginCompletedEventArgs) 
            
                  
            Dim uri As New Uri("/Page1.xaml", UriKind.RelativeOrAbsolute) 
            Me.NavigationService.Navigate(uri) 
        End Sub 
     
    End Class 

    Saturday, January 1, 2011 12:30 PM
  • You should always use UriKind.Relative

    Other than that, it looks like it should work just fine. Trying changing from UriKind.RelativeOrAbsolute to UriKind.Relative and if it's still not working (and not giving any errors), set a breakpoint in the proxy_ComprobarLoginCompleted method and see if it's ever hit and what the values are. If it does throw an exception, post details about the exception it's throwing (e.g. the type of exception, the message, and what line it's throwing it on) and we can try to figure it out from there.
    Saturday, January 1, 2011 12:40 PM
  • Hi

    Hi put this
    Imports MyClientWin7.ServiceReference1
    Imports MD5Core
    Imports MD5Managed
    Imports System.Windows


    Partial Public Class MainPage
        ....
            NavigationService.Navigate(New Uri("/Page2.xaml", UriKind.Relative))
    ...

    End Class

    And in Page2.Xaml.vb, the problems is here

        Public Sub New(ByVal codigo As String, ByVal nombre As String)
            Dim proxy As New Service1Client()

            InitializeComponent()

            'Asigno como titulo de la pagina el nombre del curso
            PageTitle.Text = nombre

            AddHandler proxy.CargarAlumnosCursoCompleted, AddressOf proxy_CargarAlumnosCursoCompleted
            proxy.CargarAlumnosCursoAsync(codigo)

        End Sub

    To test if it is the problem i change the whole public sub new to this

    Public Sub New()

            ' Llamada necesaria para el diseñador.
            InitializeComponent()

            ' Agregue cualquier inicialización después de la llamada a InitializeComponent().

        End Sub

    And it works fine!!!!


    Now, how can i pass parameters to a page?

    THANKSSS!!!!
    Saturday, January 1, 2011 12:52 PM
  • You can either include them in the Uri string (see this page for how to do that: http://msdn.microsoft.com/en-us/library/ff626521(VS.92).aspx ) or else you could add a few Shared members to the class for the page you want to pass data to (e.g. Page2) and then just set those members to the correct values before you call NavigationService.Navigate() from another page to go to that page.
     
    Once you have the values, setup the class to set the data on the appropriate elements on the page by setting the Name property for those elements in the XAML and then applying those values in the constructor after the InitializeComponent() line. If you don't use the Shared member approach, you'll probably want to save the values you parse from the NavigationContext to class members so you don't have to keep parsing them every time you need the value.

    I find using the Shared member approach easier, but either method should work fine.
    Saturday, January 1, 2011 1:06 PM
  • I've tried this

    On mainPage

      NavigationService.Navigate(New Uri("/Page1.xaml?usuario=" + user, UriKind.Relative))


    On Page1.xaml.vb

    Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs) 
            MyBase.OnNavigatedTo(e) 
     
            Dim usuario As String = "" 
     
            If NavigationContext.QueryString.TryGetValue("usuario", usuario) Then 
                InitializeComponent() 
     
                Dim proxy As New Service1Client() 
                AddHandler proxy.CargarCursosUsuarioCompleted, AddressOf proxy_CargarCursosUsuarioCompleted 
                proxy.CargarCursosUsuarioAsync(usuario) 
            End If 
     
     
        End Sub 

    And it worked fine, but when i tried to pass 2 parameters

    On page1.xaml.vb

    NavigationService.Navigate(New Uri("/Page2.xaml?codigo=" + codigo + "?nombre=" + nombre, UriKind.Relative))


    And on Page2.xaml.vb


       Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs) 
            MyBase.OnNavigatedTo(e) 
     
            Dim codigo As String = String.Empty 
            Dim nombre As String = String.Empty 
     
            If NavigationContext.QueryString.TryGetValue("codigo", codigo) Then 
                If NavigationContext.QueryString.TryGetValue("nombre", nombre) Then 
                    Dim proxy As New Service1Client() 
     
                    InitializeComponent() 
     
                    'Asigno como titulo de la pagina el nombre del curso 
                    PageTitle.Text = nombre 
     
                    AddHandler proxy.CargarAlumnosCursoCompleted, AddressOf proxy_CargarAlumnosCursoCompleted 
                    proxy.CargarAlumnosCursoAsync(codigo) 
                End If 
            End If 
     
        End Sub 


    And it doesn't work

    I'm trying to pass multiple parameters to Page2

    Would you mind (again) to help me?

    Thanks
    Saturday, January 1, 2011 1:29 PM
  • No problem.

    ? separates the page you want to go to from the parameters you want to pass.
    & is what you need to use to separate individual parameters. So

        NavigationService.Navigate(New Uri("/Page2.xaml?codigo=" + codigo + "&nombre=" + nombre, UriKind.Relative))

    You should test out what happens if the username and password have an '&' character in them since that could potentially cause a problem (or not; I'm not sure if it properly encodes and decodes special characters or if you need to do that yourself somehow; that's the reason I prefer the Shared class member way - I'm too lazy to figure that out! :) ).
    Saturday, January 1, 2011 1:39 PM
  • Thank you very much

    I will test in my application that the user can't insert & and ? characters in his password

    THANK YOU VERY MUCH AGAIN

    Saturday, January 1, 2011 1:43 PM
  • You can use the Uri.EscapeUriString or Uri.EscapeDataString to encode the info in the URL and let the user put & or ? in the password field.
    Saturday, January 1, 2011 10:44 PM
  • Thank you!! It was very helpfull!
    • Edited by leesejin Tuesday, August 13, 2019 11:18 AM
    Tuesday, August 13, 2019 11:18 AM