我正在努力将Windows商店应用转换为Windows Phone 8.对于WinRT,您可以在调用frame.navigate时将任何对象作为参数传递。 (frame.navigate(type sourcePageType,object parameter))
对于Windows手机,导航似乎有所不同,您可以通过调用uri来导航,例如:frame.navigate(new uri(“mypage.xaml”,UriKind.Relative))
Windows文档指出,您可以通过将字符串添加到uri来传递字符串作为参数。
是否有一种可接受的方式在我刚刚找不到的页面之间传递复杂对象?
答案 0 :(得分:15)
我最终扩展了NavigationService类,如下所示:
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;
}
}
然后您在源页面上调用NavigationService.Navigate("mypage.xaml", myParameter);
,并在目标页面调用var myParameter = NavigationService.GetLastNavigationData();
的OnNavigatedTo方法中调用参数数据。
答案 1 :(得分:3)
我想添加上面Zik提供的优秀答案的VB.net版本。一旦我弄清楚如何将他的代码翻译成VB,我立即使用类似于WinRT / Windows 8的方式进行导航。
我使用以下代码创建了一个模块:
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
然后导航到另一个页面:
NavigationService.Navigate("pagename.xaml", ObjectToPassToThePage)
最后,要在我的其他页面中获取该对象,请在OnNavigatedTo子目录中:
ThisPageData = NavigationService.GetLastNavigationData()
Me.DataContext = ThisPageData
归功于Zik的实际答案。
答案 2 :(得分:2)
如果您使用的是MVVM架构,则可以在使用Messenger注册后传递字符串或任何值。使用字符串(比如消息)变量创建一个模型类(比如PageMessage)。你想将字符串从homepage.xaml传递到newpage.xaml,然后在homepage.xaml中发送这样的消息
Messenger.Default.Send(new PageMessage{message="Hello World"});
在newpage.xaml中,您应该注册这样的信使,
Messenger.Default.Register<PageMessage>(this, (action) => ReceiveMessage(action));
private object ReceiveMessage(PageMessage action)
{
string receivedMessage=action.message;
return null;
}
答案 3 :(得分:0)
我在我的应用程序中所做的是将某种标识符(索引,GUID,无论如何)作为字符串传递,然后在要导航到的页面的OnNavigatedTo()方法中查找该对象。因此,对象将保留在ViewModel(或任何地方)中,您只需传递一个字符串。
答案 4 :(得分:0)
我建议在两个视图模型之间使用服务代理。
首先,定义一个视图模型定位器。在app.xaml的资源字典中创建此类的实例。将每个页面的DataContext设置为视图模型定位器的属性。有关示例,请参阅John Papa's blog。
其次,使用GetAllItems()和GetItem(string id)等方法创建服务代理。在视图模型定位器中创建此服务代理的实例。将此引用传递给两个视图模型。
第三,通过将DataContext强制转换为视图模型类型,从第二个视图访问视图模型。将导航参数传递给视图模型,以便它可以调用GetItem并填充其属性。
答案 5 :(得分:0)
无法发送非字符串的导航参数。我通常使用DataContractJsonSerializer来序列化我需要传输的数据(但要注意Uri长度限制)。 还记得使用Uri.EscapeDataString(参数)来转义查询字符串参数中的字符。
答案 6 :(得分:0)
正如@gregstoll所说,Windows Phone中最好的方法是发送一个标识符,然后利用App.ViewModel中的数据来访问您想要的实际数据。 QueryString的长度存在限制,在大多数情况下,你真的不想强调它的限制。
如果您能详细了解项目的情况,我们可以更好地帮助您确定最佳路径。
答案 7 :(得分:0)
MSDN概述了在页面之间传递非字符串参数的3种方法。其中包括:自定义导航扩展,静态属性和JSON +独立存储。代码取自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));
}
答案 8 :(得分:0)
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");
}