为什么 Frame 属性在透视项中为空
本文关键字:透视 Frame 属性 为什么 | 更新日期: 2023-09-27 18:31:32
我有一个像这样定义的透视页面:
<Grid x:Name="LayoutRoot" Background="Transparent" >
<Pivot Title="JOETZ">
<PivotItem Header="kampen" Name="PvOne">
<views:CampsPage/>
</PivotItem>
<PivotItem Header="kalender" Name="PvTwo">
<views:CalendarPage/>
</PivotItem>
<PivotItem Header="profiel" Name="PvThree">
<views:LoginPage/>
</PivotItem>
</Pivot>
</Grid>
以第一页(CampsPage
)为例:它包含一个ListBox
,概述了营地。 单击某个项目时,它应转到详细信息视图。为了导航,我认为这应该足够了:
Frame.Navigate(typeof(CampDetail), selectedCamp);
但这引起了NullReferenceException
,因为Frame
显然是null
.
另一方面,像这样进行导航是有效的:
var frame = Window.Current.Content as Frame;
if (frame == null) { return; }
frame.Navigate(typeof(CampDetail), selectedCamp);
这种方法也是如此:
var frame = ((App) Application.Current).RootFrame;
frame.Navigate(typeof(CampDetail), selectedCamp);
为什么不在透视项中设置 Frame
属性?作为后续行动:我应该如何从透视项导航?
您似乎已经找到了所需的大部分信息。我可以确认这是导航方式(正如您自己建议的那样):
var frame = (Frame)Window.Current.Content;
frame.Navigate(typeof(CampDetail), selectedCamp);
以这种方式获得Frame
是非常普遍和安全的。除非你把它放在那里,否则Window.Current.Content
里除了Frame
之外不会有任何东西。在这种情况下,根本不会有Frame
,并且无论如何您都无法像这样导航(也就是说,您必须手动更改 Window.Current.Content
属性以显示其他内容,并手动管理后退按钮)。
一些想法/建议
我建议你创建一个带有静态Navigate
方法的静态类,该方法可以完成工作(获取 Frame 并调用其 Navigate
方法)。
也许更方便的是(也)为执行导航的 UserControl 类创建一个扩展方法。这样,您只需在所有用户控件中调用this.Navigate(typeof(CampDetail), selectedCamp)
。
我还建议保持一致并始终使用此方法,并且永远不要使用 Page.Frame
属性(除非您出于某种原因确实需要)。这将使查找/解决与导航相关的问题变得更加容易,因为每个导航都将通过该方法。
您应该使用用户控件而不是页面
Page
是要在整个屏幕上显示的应用程序的一部分。它不被排除为另一个页面的一部分。你使用它的方式,它的工作方式类似于用户控件(在这种情况下你应该使用)。特定于 Page
的功能只有在使用 Frame
对象导航到它时才有效。
另一方面,用户控件和模板化控件是页面的可重用部分。因此,如果您需要在多个页面中具有一些 UI(及其功能),则可以创建这些控件之一。
因此,我建议您将<views:CampsPage/>
,<views:CalendarPage/>
和<views:LoginPage/>
更改为UserControls而不是Pages。如果还需要页面(用于导航目的),请制作仅显示这些用户控件的页面。
"硬件后退"按钮
你似乎不再需要这个了,但无论如何我都会放几行。
默认情况下,"后退"按钮仅告诉关闭应用程序。您可以手动处理后退按钮,并使用 Window.Current.Content
中的Frame
GoBack()
如果可能,则会HardwareButtons.BackPressed
事件执行一些非默认操作。
编辑
我对后退按钮的默认操作是错误的并修复了它。我很确定它曾经自动导航回堆栈。
我不确定这是否是最佳答案(我确定它不是:)但应该工作。
问题是CampsPage
是我怀疑 Page 类在 Frame 以外的其他容器中。您尚未导航到该页面,它不在Window.Current.Content
内部 - 它在 Pivot 内部。因此,它的框架属性是null
。
这是我的丑陋方法:
使用 DependencyProperty 扩展 Page 类 - 对父页面的引用:
public class ExtendedPage : Page
{
public Page ParentPage
{
get { return (Page)GetValue(ParentPageProperty); }
set { SetValue(ParentPageProperty, value); }
}
public static readonly DependencyProperty ParentPageProperty =
DependencyProperty.Register("ParentPage", typeof(Page), typeof(Page), new PropertyMetadata(0));
}
然后,将您的CampsPage
(和其他)设置为此扩展页面类型。然后将 ParentPage 属性绑定到框架内的当前页面:
<Page Name="MyMainPage" ... rest of things ...>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Pivot Title="JOETZ">
<PivotItem Header="kampen" Name="PvOne">
<local:CampsPage ParentPage="{Binding ElementName=MyMainPage}"/>
</PivotItem>
... rest of the code
然后,您可以像这样在CampsPage
中导航:
ParentPage.Frame.Navigate(typeof(DetailPage));
就像我说过的,可能有赌注解决方案,但除非没有其他解决方案,否则也许这会很有用。
您可以从 GitHub 下载的示例。