Reputation: 243
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
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
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
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
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
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
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
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
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
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