我一直在使用NavigationService
的{{1}}方法导航到我的WP7 Silverlight应用中的其他页面:
Navigate
从NavigationService.Navigate(new Uri("/Somepage.xaml?val=dreas", UriKind.Relative));
开始,我按如下方式检索查询字符串参数:
Somepage.xaml
我现在需要一种以类似方式传递复杂对象的方法。每次我需要将对象传递给新页面时,如何才能执行而不必序列化对象?
答案 0 :(得分:14)
这是一个非常复杂的问题,这里没有简单的解决方案。没有神奇的API可以用于任何应用程序来解决这个问题。
传递导航数据的核心问题是Tombstoning 。默认情况下逻辑删除的唯一数据是导航URI。因此,如果您使用的是QueryString参数,它将通过逻辑删除和您的代码自动获取。只要您手动传递对象的实例,就必须自己手动为该实例进行逻辑删除。
因此,如果您导航到“/CowDetails.xaml?ID=1”,您的页面可能只需要通过ID查询字符串参数就可以获得完美的逻辑删除。但是,如果你以某种方式为CowDetails页面提供了一个“new Cow(){ID = 1}”,那么你必须自己确保墓碑和zombificate这个值。
此外,还有时间问题。在调用NavigationService.Navigate时,您正在导航的页面也没有实际的实例。因此,即使您正在导航到FooPage并准备好FooData,也无法立即将FooPage连接到FooData。您必须等到PhoneApplicationFrame.Navigated事件被触发才能为FooPage提供FooData。
我通常处理这个问题的方法是:
答案 1 :(得分:9)
App.xaml.cs - > App类,在那里添加一个字段/属性。要访问它,如果是静态使用:
App.MyComplexObject
或者如果不是staic
(App.Current as App).MyComplexObject;
答案 2 :(得分:5)
有一个非常简单的解决方案可以解决这个问题。请考虑以下示例 Windows Phone应用程序有以下两个页面, Page1.xaml 和 Page2.xaml 让我们从 Page1.xaml 说我们正在导航到 Page2.xaml 。当您调用 NavigationService.Navigate 方法
时,导航周期开始因此我们在导航开始的页面中获取其他页面的引用。
public class PhoneApplicationBasePage : PhoneApplicationPage
{
private object navParam = null;
protected object Parameter{get;private set;}
//use this function to start the navigation and send the object that you want to pass
//to the next page
protected void Navigate(string url, object paramter = null)
{
navParam = paramter;
this.NavigationService.Navigate(new Uri(url, UriKind.Relative));
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
//e.Content has the reference of the next created page
if (e.Content is PhoneApplicationBasePage )
{
PhoneApplicationBasePage page = e.Content as PhoneApplicationBasePage;
if (page != null)
{ page.SendParameter(navParam); navParam=null;}
}
}
private void SendParameter(object param)
{
if (this.Parameter == null)
{
this.Parameter = param;
this.OnParameterReceived();
}
}
protected virtual void OnParameterReceived()
{
//Override this method in you page. and access the **Parameter** property that
// has the object sent from previous page
}
}
因此,在我们的 Page1.xaml.cs 中,我们只需拨打Navigate("/Page2.xaml",myComplexObject)
即可。在您的 Page2.xaml.cs 中,我们将覆盖 OnParameterReceived 方法
protected override void OnParameterReceived()
{
var myComplexObjext = this.Parameter;
}
还可以通过 PhoneApplicationBasePage
中的更多调整来处理逻辑删除问题答案 3 :(得分:1)
有争议的解决方案,如果有的话,将其作为临时解决方案。
在应用程序的命名空间下创建此选项,以获取必要的页面。
public static class VarsForPages {
// Be sure to include public static.
public static SomeClass SomeClassObject;
public static List<string> SomeList = new List<string>();
public static string SomeData = "SomeValue";
}
// The syntax for referencing the data
VarsForPages.SomeClassObject;
VarsForPages.SomeList;
VarsForPages.SomeData;
现在,您可以在应用程序的任何位置引用SomeClassObject,SomeList,SomeData。
注意:像任何全球数据一样,厌倦了许多访问&amp;可以对全局数据进行的修改。我这样说,因为我曾经有一个列表增加的大小,但我的应用程序中的一个页面依赖于列表的大小有一些价值,这导致了一个错误。不要忘记,数据是全球性的。
答案 4 :(得分:1)
我希望我能回复vjsrinath上面的回复; IMO是实现这一目标的最佳方式。非常感谢!!
这可能是我见过的最接近iOS模型的工作方式,从第一页调用performSegue(== NavigateTo)。然后你得到一个名为prepareForSegue的回调函数,它允许你在目标页面中设置变量,设置委托(通常是自己的),那种东西。
对于复杂的对象传递,它会在URL中传递params。
作为一个明确的例子,假设我想将我的应用程序的版本字符串传递到一个单独的项目中的“关于”框中:
在通话类中:
private void About_Click(object sender, EventArgs e)
{
NavigationService.Navigate(new Uri("/Library;component/Pages/About.xaml", UriKind.Relative));
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
if (e.Content is About)
{
About page = e.Content as About;
if (page != null)
{
page.VersionString = App.VersionText;
}
}
base.OnNavigatedFrom(e);
}
在About课程中:
public partial class About : PhoneApplicationPage
{
public string VersionString { get; set; }
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
versionTextBlock.Text = VersionString;
}
}
这当然是一个非常简单的例子,但你传递的属性可能是任何对象,这使得它非常强大。当然它可以包括回调,例如“saveButtonPressed”等,因此保存处理可以在调用类中完成,而不是呈现的视图,这对于代码整洁而言非常糟糕。如,
page.OnSaveButtonPressed = this.SaveButtonPressedHandler; // Pass object to save as parameter