locked
How to navigate to a new page after photo chooser completes? RRS feed

  • Question

  • I have created a listbox that displays pictures that the user has chosen using the photoChooser. I'm trying to make the listbox update after the user chooses the photo. The way I'm trying to do it is buy either navigating to a new page that says loading or something or just navigating to the page that I'm already on if that works. But I cant figure out how to code that. When I do the normal
    NavigationService.Navigate(new Uri("/page.xaml", UriKind.Relative));  
     

     

     

    Visual Studio gives me a null reference exception. Heres my full code:

     

     

     

    void OnPhotoChooserCompleted(object sender, PhotoResult e)  
            {  
                IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;  
                if (!settings.Contains("pictureNumber"))  
                {  
                    settings.Add("pictureNumber""0");  
     
                }  
     
                int pictureNumber = int.Parse(settings["pictureNumber"as string);  
                using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())  
                {  
     
                    var bi = new BitmapImage();  
                    bi.SetSource(e.ChosenPhoto);  
                    var wb = new WriteableBitmap(bi);  
                    using (var isoFileStream = isoStore.CreateFile("pic." + pictureNumber + ".jpg"))  
                    {  
                        var width = wb.PixelWidth;  
                        var height = wb.PixelHeight;  
                        Extensions.SaveJpeg(wb, isoFileStream, width, height, 0, 100);  
                    }  
                }  
     
                pictureNumber++;  
                string pictureNumberString = pictureNumber.ToString();  
                settings["pictureNumber"] = pictureNumberString;  
                settings.Save();  
                NavigationService.Navigate(new Uri("/About.xaml", UriKind.Relative));  
         }    

    By the way About.xaml is not the page I'm on currently so that is not the problem. Also, if you have another idea on how to refresh the listbox thats fine too.

    Thanks,
    bigwolf

     

     

     

    Wednesday, January 18, 2012 1:19 AM

All replies

  • Really need help with this guys!
    Wednesday, January 18, 2012 5:07 AM
  • It seems you're using a Silverlight app so I'm not sure if this still applies since the photo app i'm working on is done in XNA, but what I did is used game states and switch statements to navigate to another part of my app. I initiate the photo chooser in one game state, and once the task is completed, I change the current state to the next game state. Each game state is like another page. Like I said, I don't if that works for Silverlight apps as I have no experience with Silverlight.

    Another thing you could possibly try is using a goto statement in C#. It's probably not a good idea to use it a lot, but it should get the job done. It's similar to switch statements & game states, but it doesn't require the use of game states if it's not supported by silverlight.
    Wednesday, January 18, 2012 5:38 AM
  • It seems you're using a Silverlight app so I'm not sure if this still applies since the photo app i'm working on is done in XNA, but what I did is used game states and switch statements to navigate to another part of my app. I initiate the photo chooser in one game state, and once the task is completed, I change the current state to the next game state. Each game state is like another page. Like I said, I don't if that works for Silverlight apps as I have no experience with Silverlight.

    Another thing you could possibly try is using a goto statement in C#. It's probably not a good idea to use it a lot, but it should get the job done. It's similar to switch statements & game states, but it doesn't require the use of game states if it's not supported by silverlight.


    Yeah I dont think the game states thing applies to silverlight. Could you explain more about the goto statement?

    Thanks,
    bigwolf
    Wednesday, January 18, 2012 5:06 PM
  • Anyone else have an idea?
    Wednesday, January 18, 2012 6:21 PM
  • Investigate the NullReferenceException. Is NavigationService null??? Or is the exception thrown by something the NavigationService does internally?

    Another idea: Does OnPhotoChooserCompleted run on the UI thread? If not, maybe (I haven't tested) you need to DispatcherBeginInvoke( () => {NavigationService.Navigate (... );});?
    Wednesday, January 18, 2012 7:38 PM
  • Here's a very simple goto example:

    page1:  
    {  
      this.Exit();  
    }  
     
    if(num == 1)  
    {  
      goto page1;  

    Now if you're going to use that, you'll have to do it at the code level in C#. After your photochooser task is completed, just use goto and send it to the page you want to navigate to. So in my code where I have "page1:", you'll want to put that wherever you're navigating too. Once the goto is activated, it will go to that block of code and do whatever is inside that block and then move on. You don't really need to have anything in that block either. It just causes your program to jump to wherever the goto statement directs it to go.
    Wednesday, January 18, 2012 8:07 PM
  • Investigate the NullReferenceException. Is NavigationService null??? Or is the exception thrown by something the NavigationService does internally?

    Another idea: Does OnPhotoChooserCompleted run on the UI thread? If not, maybe (I haven't tested) you need to DispatcherBeginInvoke( () => {NavigationService.Navigate (... );});?

    How do I investigate it? And can you explain more about the dispatcher begin invoke thing?

    Thanks,
    Bigwolf
    Wednesday, January 18, 2012 8:16 PM
  • Here's a very simple goto example:

    page1:  
    {  
      this.Exit();  
    }  
     
    if(num == 1)  
    {  
      goto page1;  

    Now if you're going to use that, you'll have to do it at the code level in C#. After your photochooser task is completed, just use goto and send it to the page you want to navigate to. So in my code where I have "page1:", you'll want to put that wherever you're navigating too. Once the goto is activated, it will go to that block of code and do whatever is inside that block and then move on. You don't really need to have anything in that block either. It just causes your program to jump to wherever the goto statement directs it to go.


    I just tried it and I got a bunch of errors. Maybe its only an xna thing?

    Thanks,
    bigwolf
    Wednesday, January 18, 2012 10:37 PM
  • Investigate the NullReferenceException. Is NavigationService null??? Or is the exception thrown by something the NavigationService does internally?

    Another idea: Does OnPhotoChooserCompleted run on the UI thread? If not, maybe (I haven't tested) you need to DispatcherBeginInvoke( () => {NavigationService.Navigate (... );});?

    How do I investigate it? And can you explain more about the dispatcher begin invoke thing?

    Thanks,
    Bigwolf

    Okay I tried it, heres the updated code:
    void OnPhotoChooserCompleted(object sender, PhotoResult e)  
            {  
                IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;  
                if (!settings.Contains("pictureNumber"))  
                {  
                    settings.Add("pictureNumber""0");  
     
                }  
     
                int pictureNumber = int.Parse(settings["pictureNumber"as string);  
                using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())  
                {  
     
                    var bi = new BitmapImage();  
                    bi.SetSource(e.ChosenPhoto);  
                    var wb = new WriteableBitmap(bi);  
                    using (var isoFileStream = isoStore.CreateFile("pic." + pictureNumber + ".jpg"))  
                    {  
                        var width = wb.PixelWidth;  
                        var height = wb.PixelHeight;  
                        Extensions.SaveJpeg(wb, isoFileStream, width, height, 0, 100);  
                    }  
                }  
     
                pictureNumber++;  
                string pictureNumberString = pictureNumber.ToString();  
                settings["pictureNumber"] = pictureNumberString;  
                settings.Save();  
                DispatcherBeginInvoke(()=>{NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));});  
     
                 
         } 
    Unfortunately, visual studio gave another error: "The name 'DispatcherBeginInvoke' does not exist in the current context." Do you know why? Am I doing the syntax wrong?

    Thanks,
    bigwolf

    Wednesday, January 18, 2012 10:42 PM
  • You forgot the '.' (dot) in Dispatcher

    Dispatcher.BeginInvoke(.... 

    Wednesday, January 18, 2012 10:45 PM
  • You forgot the '.' (dot) in Dispatcher

    Dispatcher.BeginInvoke(.... 


    Yes I did! Thanks, but unfortunately I'm now getting another null reference exception.

    Anymore thoughts?
    bigwolf
    Wednesday, January 18, 2012 10:54 PM
  • There's nothing wrong with your Navigate statement or how you're using it. I'm not convinced it is the problem. What is on the call stack when the exception happens? Have you set a breakpoint at the beginning of OnPhotoChooserCompleted and stepped through the code execution?

    BTW, why aren't you checking the value of e.TaskResult (the return code from the photo chooser)? The user can return without choosing anything, and you'll still try to process it. See the example: http://msdn.microsoft.com/en-us/library/hh394019(v=vs.92).aspx 


    Richard Woo
    Wednesday, January 18, 2012 11:56 PM
  • There's nothing wrong with your Navigate statement or how you're using it. I'm not convinced it is the problem. What is on the call stack when the exception happens? Have you set a breakpoint at the beginning of OnPhotoChooserCompleted and stepped through the code execution?

    BTW, why aren't you checking the value of e.TaskResult (the return code from the photo chooser)? The user can return without choosing anything, and you'll still try to process it. See the example: http://msdn.microsoft.com/en-us/library/hh394019(v=vs.92).aspx 


    Richard Woo
    I'm not sure how to check what's on the call stack. (sorry im a n00b programmer) by the way, everything works if I remove that line of code. To make it update I can just use a button to navigate to another page and than navigate back. But, I want it to update automatically. If you have a different way to do I thats fine too.

    I was planning on adding code to check that after I'd finished everything else since that's more of a minor problem. I guess I'll add it now though since you reminded me.

    Thanks,
    Bigwolf

    Thursday, January 19, 2012 1:05 AM
  • In the example I linked earlier (http://msdn.microsoft.com/en-us/library/hh394019(v=vs.92).aspx), you can add a navigation to another page and it will work fine. That's why I don't think NavigationService.Navigate is the problem. It could be a problem that actually occurred earlier but didn't manifest itself until the Navigate call.

    I'm not sure how to check what's on the call stack.
    You'll do yourself a big favor if you familiarize yourself with the debugging tools in Visual Studio. You can debug much faster if you can examine what is happening in your code, and if you ask for help it will allow you to provide more detailed information.

    When the debugger is running, open the call stack window by going to the Debug menu ==> Windows ==> Call Stack (or press alt-7). It will display the stack when the debugger is paused (e.g. at a breakpoint or exception). While you're at it, look over what else is in the Debug menu. To set a breakpoint, right click on the statement you want to stop at and choose the Breakpoint selection. I recommend that you set a breakpoint at the beginning of OnPhotoChooserCompleted and step through each statement (Step Over, F7) until you get to the exception. At each statement, you can view (and modify) object values and verify they are what you expect.


    Richard Woo
    Thursday, January 19, 2012 8:52 AM
  • In the example I linked earlier (http://msdn.microsoft.com/en-us/library/hh394019(v=vs.92).aspx), you can add a navigation to another page and it will work fine. That's why I don't think NavigationService.Navigate is the problem. It could be a problem that actually occurred earlier but didn't manifest itself until the Navigate call.

    I'm not sure how to check what's on the call stack.
    You'll do yourself a big favor if you familiarize yourself with the debugging tools in Visual Studio. You can debug much faster if you can examine what is happening in your code, and if you ask for help it will allow you to provide more detailed information.

    When the debugger is running, open the call stack window by going to the Debug menu ==> Windows ==> Call Stack (or press alt-7). It will display the stack when the debugger is paused (e.g. at a breakpoint or exception). While you're at it, look over what else is in the Debug menu. To set a breakpoint, right click on the statement you want to stop at and choose the Breakpoint selection. I recommend that you set a breakpoint at the beginning of OnPhotoChooserCompleted and step through each statement (Step Over, F7) until you get to the exception. At each statement, you can view (and modify) object values and verify they are what you expect.


    Richard Woo


    Okay I'll try that as soon as I can. My powers out at the moment unfortunately.

    Thursday, January 19, 2012 10:28 PM
  • In the example I linked earlier (http://msdn.microsoft.com/en-us/library/hh394019(v=vs.92).aspx), you can add a navigation to another page and it will work fine. That's why I don't think NavigationService.Navigate is the problem. It could be a problem that actually occurred earlier but didn't manifest itself until the Navigate call.

    I'm not sure how to check what's on the call stack.
    You'll do yourself a big favor if you familiarize yourself with the debugging tools in Visual Studio. You can debug much faster if you can examine what is happening in your code, and if you ask for help it will allow you to provide more detailed information.

    When the debugger is running, open the call stack window by going to the Debug menu ==> Windows ==> Call Stack (or press alt-7). It will display the stack when the debugger is paused (e.g. at a breakpoint or exception). While you're at it, look over what else is in the Debug menu. To set a breakpoint, right click on the statement you want to stop at and choose the Breakpoint selection. I recommend that you set a breakpoint at the beginning of OnPhotoChooserCompleted and step through each statement (Step Over, F7) until you get to the exception. At each statement, you can view (and modify) object values and verify they are what you expect.


    Richard Woo


    Everything seemed normal to me, though I definately could have missed something, except that the exception wasn't thrown when I was on the line, it was thrown at the second curly brace after it. I implemented the checker like you said so heres the updated code:
    void OnPhotoChooserCompleted(object sender, PhotoResult e)  
            {  
                if (e.TaskResult == TaskResult.OK)  
                {  
     
                    IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;  
                    if (!settings.Contains("pictureNumber"))  
                    {  
                        settings.Add("pictureNumber""0");  
     
                    }  
     
                    int pictureNumber = int.Parse(settings["pictureNumber"as string);  
                    using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())  
                    {  
     
                        var bi = new BitmapImage();  
                        bi.SetSource(e.ChosenPhoto);  
                        var wb = new WriteableBitmap(bi);  
                        using (var isoFileStream = isoStore.CreateFile("pic." + pictureNumber + ".jpg"))  
                        {  
                            var width = wb.PixelWidth;  
                            var height = wb.PixelHeight;  
                            Extensions.SaveJpeg(wb, isoFileStream, width, height, 0, 100);  
                        }  
                    }  
     
                    pictureNumber++;  
                    string pictureNumberString = pictureNumber.ToString();  
                    settings["pictureNumber"] = pictureNumberString;  
                    settings.Save();  
                    Dispatcher.BeginInvoke(() => { NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative)); });  
     
                }  
          
    I bolded and underlined the curly brace. To clarify, it didnt throw the exception on the curly brace, it threw the exception on the NavigationService line but it was after I got to the curly brace when I was stepping through.
    Tuesday, January 24, 2012 12:20 AM
  • Could it be that something else is null and is interfering with it?
    Tuesday, January 24, 2012 2:50 PM
  • You said navigating back to the current page is an option, but isn't that what happens when a task completes by default? I think you just may be able to remove the  NavigationService.Navigate(new Uri("/[Page Name].xaml", UriKind.Relative)); line and have the page refresh. I think The Page.OnNavigatedTo or page constructor will get called again and you can do your listbox updates there.

    Alternatively, you may try navigating away from the page within the OnNavigatedTo method. There may be some null value in your settings serialization, but I am thinking that the OnPhotoChooserCompleted event handler might be outside the page scope. Let me know if this works.
    Tuesday, January 24, 2012 3:43 PM
  • You said navigating back to the current page is an option, but isn't that what happens when a task completes by default? I think you just may be able to remove the  NavigationService.Navigate(new Uri("/[Page Name].xaml", UriKind.Relative)); line and have the page refresh. I think The Page.OnNavigatedTo or page constructor will get called again and you can do your listbox updates there.


    Alternatively, you may try navigating away from the page within the OnNavigatedTo method. There may be some null value in your settings serialization, but I am thinking that the OnPhotoChooserCompleted event handler might be outside the page scope. Let me know if this works.


    Unfortunately that will not work because I add the photo to the isolated storage and therefore the listbox during the onphotochoosercompleted method. The page is refreshing before that but I need it to after the photo is added. Let me know if I'm misunderstanding or if you have any other ideas.




    thanks,

    Bigwolf

    Wednesday, January 25, 2012 1:17 AM
  • Bigwolf,

    I copied and pasted your code into a project and it worked fine for me, navigation and all. Try it for yourself in the Photo Chooser Task example. There doesn't seem to be anything fundamentally wrong with the code snippet you posted. The problem might be with your MainPage. Set a breakpoint in the MainPage constructor and see if it hits it. Also test what happens if you add a new default page to your project and navigate to it (instead of MainPage).

    Regarding the ListBox, is it databound? If the binding is set up properly, you can update the view model and the ListBox will update automatically.


    Richard Woo
    Wednesday, January 25, 2012 7:22 AM
  • Bigwolf,

    I copied and pasted your code into a project and it worked fine for me, navigation and all. Try it for yourself in the Photo Chooser Task example. There doesn't seem to be anything fundamentally wrong with the code snippet you posted. The problem might be with your MainPage. Set a breakpoint in the MainPage constructor and see if it hits it. Also test what happens if you add a new default page to your project and navigate to it (instead of MainPage).

    Regarding the ListBox, is it databound? If the binding is set up properly, you can update the view model and the ListBox will update automatically.


    Richard Woo


    Richard,

    I tried pointing it toward a different page and it still gave me the null error. I'm not sure whats going on here since it works in a different project...

    My listbox is set up sort of weirdly. In the xaml its set to: ItemsSource="{Binding Collection}"  In the code behind to add the items I have:
    private void SetListBox2()  
            {  
                Pictures.Items.Clear();  
                byte[] byte1;  
                using (IsolatedStorageFile insISF = IsolatedStorageFile.GetUserStoreForApplication())  
                    foreach (string filename in insISF.GetFileNames("smallpic.*"))  
                    {  
                        using (IsolatedStorageFileStream isfs = insISF.OpenFile(filename, FileMode.Open, FileAccess.Read))  
                        {  
                            byte1 = new byte[isfs.Length];  
                            isfs.Read(byte1, 0, byte1.Length);  
                            isfs.Close();  
                        }  
                        Image image = new Image();  
                        MemoryStream ms = new MemoryStream(byte1);  
                        BitmapImage bi = new BitmapImage();  
                        bi.SetSource(ms);  
                        image.Source = bi;  
                        Pictures.Items.Add(image);  
                    }  
            } 
    (the listbox is named "Pictures")

    Also, I figured out a way to have it update! Its kind of awkward so if you think I can update the view model that might be better. But, I realized that the page runs the OnNavigatedTo method after the photochooser completes so when the user first hits the photo button I coded this:
    public void newPhoto()  
            {  
                PhotoChooserTask photoChooser = new PhotoChooserTask();  
                photoChooser.Completed += OnPhotoChooserCompleted;  
                (App.Current as App).IsAppReActivated = true;  
                photoChooser.Show();  
                  
            } 
    Notice IsAppReActivated is set to "true"

    Than whenever the page loads I coded this:
    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)  
            {  
                base.OnNavigatedTo(e);  
                if ((App.Current as App).IsAppReActivated)  
                {  
                    NavigationService.Navigate(new Uri("/pleaseWait.xaml", UriKind.Relative));  
                    (App.Current as App).IsAppReActivated = false;  
                }  
            } 

    It displays a page that says "please wait..." on it for about half a second before this method runs on the please wait page:
    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)  
            {  
                base.OnNavigatedTo(e);  
     
                NavigationService.Navigate(new Uri("/picturesAndNotes.xaml", UriKind.Relative));  
                (App.Current as App).IsAppReActivated = false;  
     
            } 

    And Ta Da! updated listbox. I'd prefer to not have the please wait page so if you have another idea that would be great but otherwise I can live with this.

    Thanks for all your help,
    Bigwolf
    Thursday, January 26, 2012 4:15 AM
  • You should only need to load the entire Pictures.Items list during application startup or after tombstoning, i.e. when the list is null or uninitialized. In OnPhotoChooserTaskCompleted, you can add the one new image to Pictures.Items, and the ListBox should update if everything is set up properly.


    Richard Woo
    Thursday, January 26, 2012 8:02 AM
  • You should only need to load the entire Pictures.Items list during application startup or after tombstoning, i.e. when the list is null or uninitialized. In OnPhotoChooserTaskCompleted, you can add the one new image to Pictures.Items, and the ListBox should update if everything is set up properly.


    Richard Woo


    Alright that sounds logical actually but for some reason its not working... I just tried this and it didnt give me an error but the listbox didn't update.
    void OnPhotoChooserCompleted(object sender, PhotoResult e)  
            {  
                if (e.TaskResult == TaskResult.OK)  
                {  
     
                    IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;  
                    if (!settings.Contains("pictureNumber"))  
                    {  
                        settings.Add("pictureNumber""0");  
     
                    }  
     
                    int pictureNumber = int.Parse(settings["pictureNumber"as string);  
                    using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())  
                    {  
     
                        var bi = new BitmapImage();  
                        bi.SetSource(e.ChosenPhoto);  
                        var wb = new WriteableBitmap(bi);  
                        using (var isoFileStream = isoStore.CreateFile("smallpic." + pictureNumber + ".jpg"))  
                        {  
                            //var width = wb.PixelWidth;  
                            //var height = wb.PixelHeight;  
                            var width = 109;  
                            var height = 109;  
                            Extensions.SaveJpeg(wb, isoFileStream, width, height, 0, 100);  
                        }  
                    }  
                    using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())  
                    {  
     
                        var bi = new BitmapImage();  
                        bi.SetSource(e.ChosenPhoto);  
                        var wb = new WriteableBitmap(bi);  
                        using (var isoFileStream = isoStore.CreateFile("pic." + pictureNumber + ".jpg"))  
                        {  
                            var width = wb.PixelWidth;  
                            var height = wb.PixelHeight;  
                            Extensions.SaveJpeg(wb, isoFileStream, width, height, 0, 100);  
                        }  
                    }  
                    byte[] byte1;  
                    using (IsolatedStorageFile insISF = IsolatedStorageFile.GetUserStoreForApplication())  
                    using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())  
                    using (IsolatedStorageFileStream isfs = insISF.OpenFile("smallpic." + pictureNumber + ".jpg", FileMode.Open, FileAccess.Read))  
                    {  
                        byte1 = new byte[isfs.Length];  
                        isfs.Read(byte1, 0, byte1.Length);  
                        isfs.Close();  
                    }  
                    Image image = new Image();  
                    MemoryStream ms = new MemoryStream(byte1);  
                    BitmapImage bit = new BitmapImage();  
                    bit.SetSource(ms);  
                    image.Source = bit;  
                    Pictures.Items.Add(image);  
                    pictureNumber++;  
                    string pictureNumberString = pictureNumber.ToString();  
                    settings["pictureNumber"] = pictureNumberString;  
                    settings.Save();  
                }  
              
         } 

    Maybe my listbox is screwed up?

    Thanks,
    bigwolf
    Thursday, January 26, 2012 2:47 PM
  • Try calling Pictures.UpdateLayout() at the end. You aren't using a view model. I suggest that you look at the MVVM pattern that Silverlight was designed for. The default Databound application is an example.
    Thursday, January 26, 2012 5:24 PM