Mr. Spoof
Mr. Spoof

Reputation: 243

How do I pass non-string parameters between pages in windows phone 8?

I'm working on converting a windows store app to windows phone 8. For WinRT, you could pass any object as a parameter when calling frame.navigate. (frame.navigate(type sourcePageType, object parameter))

The navigation seems to work differently for windows phone, you navigate by calling into a uri, like: frame.navigate(new uri("mypage.xaml", UriKind.Relative))

The windows documentation notes that you can pass a string as a parameter by adding it to the uri.

Is there an accepted way of passing complex objects between pages that I just haven't found?

Upvotes: 11

Views: 7589

Answers (9)

Jaihind
Jaihind

Reputation: 2778

Yes there is a way to use a complex object in different pages in wp8 or wp7. You can use complex objects between pages by IsolatedStorageSettings.

IsolatedStorageSettings AppSettings = IsolatedStorageSettings.ApplicationSettings;

// to save an object in isolatedstoragesettings
if (!AppSettings.Contains("ObjectKey"))
      AppSettings.Add("ObjectKey", Your object value);
else
      AppSettings["ObjectKey"] = Your object value;

// to retrieve value of an object from isolatedstoragesettings
if(AppSettings.Contains("ObjectKey"))
    {
    var objectValue = (Cast object to type)AppSettings["ObjectKey"];
    //Remove 
     AppSettings.Remove("ObjectKey");
    } 

Upvotes: 0

Ramesh
Ramesh

Reputation: 415

If you are using MVVM architecture,then you can pass string or any value after registering using Messenger. Create a model class (say PageMessage) with a string(say message) variable. You want to pass string from homepage.xaml to newpage.xaml,then in homepage.xaml just send the message like this

Messenger.Default.Send(new PageMessage{message="Hello World"});

In the newpage.xaml,you should register the messenger like this,

Messenger.Default.Register<PageMessage>(this, (action) => ReceiveMessage(action));

 private object ReceiveMessage(PageMessage action)
 {
    string receivedMessage=action.message;
    return null;
 }

Upvotes: 2

brendan
brendan

Reputation: 1735

MSDN outlines 3 methods for passing non-string parameters between pages. These include: custom navigation extensions, static properties and JSON+isolated storage. Code taken from Microsoft:

   /// <summary> 
   /// Custom Navigation Extensions. 
   /// </summary> 
   /// <param name="sender"></param> 
   /// <param name="e"></param> 
   private void btnMethod1_Click(object sender, RoutedEventArgs e) 
   { 
       NavigationService.Navigate("/Result.xaml?name=1", listString); 
   } 


   /// <summary> 
   /// Static properties 
   /// </summary> 
   /// <param name="sender"></param> 
   /// <param name="e"></param> 
   private void btnMethod2_Click(object sender, RoutedEventArgs e) 
   { 
       App.ObjectNavigationData = listString; 
       NavigationService.Navigate(new Uri("/Result.xaml?name=2", UriKind.Relative)); 
   } 


   /// <summary> 
   /// Json + IsolatedStorage 
   /// </summary> 
   /// <param name="sender"></param> 
   /// <param name="e"></param> 
   private void btnMethod3_Click(object sender, RoutedEventArgs e) 
   { 
       string filePath = "objectData"; 


       using (IsolatedStorageFile isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication()) 
       { 
           if (isolatedStorage.FileExists(filePath)) 
           { 
               isolatedStorage.DeleteFile(filePath); 
           } 


           using (IsolatedStorageFileStream fileStream = isolatedStorage.OpenFile(filePath, FileMode.Create, FileAccess.Write)) 
           { 
               string writeDate = string.Empty; 


               // Json serialization. 
               using (MemoryStream ms = new MemoryStream()) 
               { 
                   var ser = new DataContractJsonSerializer(typeof(List<string>)); 
                   ser.WriteObject(ms, listString); 
                   ms.Seek(0, SeekOrigin.Begin); 
                   var reader = new StreamReader(ms); 
                   writeDate = reader.ReadToEnd(); 
               } 


               // Save to IsolatedStorage. 
               using (StreamWriter writer = new StreamWriter(fileStream)) 
               { 
                   writer.WriteLine(writeDate); 
               } 
           } 
       } 


       NavigationService.Navigate(new Uri("/Result.xaml?name=3", UriKind.Relative)); 
   } 

Upvotes: 0

pumpkinszwan
pumpkinszwan

Reputation: 1352

I want to just add a VB.net version of the great answer provided by Zik above. Once I figured out how to translate his code to VB I immediately had navigation working similarly to the WinRT/Windows 8 way.

I created a module with the following code:

Module NavigationExtensionsModule

Sub New()
End Sub
Private _navigationData As Object = Nothing

<System.Runtime.CompilerServices.Extension> _
Public Sub Navigate(service As NavigationService, page As String, data As Object)
    _navigationData = data
    service.Navigate(New Uri(page, UriKind.Relative))
End Sub

<System.Runtime.CompilerServices.Extension> _
Public Function GetLastNavigationData(service As NavigationService) As Object
    Dim data As Object = _navigationData
    _navigationData = Nothing
    Return data
End Function
End Module

And then navigate to another page like this:

 NavigationService.Navigate("pagename.xaml", ObjectToPassToThePage)

And lastly, to get that object in my other page, in the OnNavigatedTo sub:

ThisPageData = NavigationService.GetLastNavigationData()

Me.DataContext = ThisPageData

Credit to Zik for the actual answer.

Upvotes: 3

Zik
Zik

Reputation: 750

I ended up extending the NavigationService class, like so:

public static class NavigationExtensions
{
    private static object _navigationData = null;

    public static void Navigate(this NavigationService service, string page, object data)
    {
        _navigationData = data;
        service.Navigate(new Uri(page, UriKind.Relative));
    }

    public static object GetLastNavigationData(this NavigationService service)
    {
        object data = _navigationData;
        _navigationData = null;
        return data;
    }
}

Then you'd call NavigationService.Navigate("mypage.xaml", myParameter); on the source page, and in the OnNavigatedTo method of the target page call var myParameter = NavigationService.GetLastNavigationData(); to get the parameter data.

Upvotes: 15

Atley
Atley

Reputation: 230

As @gregstoll stated, the best methodology in Windows Phone is to send an identifier and then utilize the data in your App.ViewModel to access the actual data that you want. There are limitations on length of the QueryString and for the most part, you really do not want to stress this to it's limits.

If you can tell a bit more about your project's scenario, we could better assist you in determining the best path to take.

Upvotes: 0

dotMorten
dotMorten

Reputation: 1966

There is no way to send a navigation parameter that is not a string. I usually use DataContractJsonSerializer to serialize the data I need to transfer (but beware of Uri length limitations). Also remember to use Uri.EscapeDataString(parameter) to escape the characters in your querystring parameter.

Upvotes: 0

Michael L Perry
Michael L Perry

Reputation: 7435

I'd recommend using a service agent between two view models.

First, define a view model locator. Create an instance of this class in a resource dictionary in app.xaml. Set the DataContext of each page to a property of the view model locator. See John Papa's blog for an example.

Second, create a service agent with methods like GetAllItems() and GetItem(string id). Create an instance of this service agent in the view model locator. Pass this reference into both view models.

Third, access the view model from the second view by casting the DataContext to the view model type. Pass the navigation parameter to the view model so that it can call GetItem and populate its properties.

Upvotes: 0

gregstoll
gregstoll

Reputation: 1318

What I've done in my apps is pass some sort of identifier (index, GUID, whatever) as a string, and then look up the object in the OnNavigatedTo() method of the page you want to navigate to. So the objects will stay stored in the ViewModel (or wherever) and you can just pass a string.

Upvotes: 0

Related Questions