所以我有一个带有Pivot
项的XAML页面的Windows 10应用程序,Pivot
的默认行为是每当您导航到包含Pivot
的页面时, Pivot
上的第一个项目会立即被选中。我想要做的是在Pivot
运行的第一项之前执行一些代码。
上下文代码
public sealed partial class ContentFrame : Page
{
private IMobileServiceTable<News> NewsItems = App.MobileService.GetTable<News>();
private List<News> AllNews;
private List<News> Windows = new List<News>();
private List<News> Apple = new List<News>();
private List<News> Google = new List<News>();
private List<News> Other = new List<News>();
private List<News> Top = new List<News>();
private string WeekID;
public ContentFrame()
{
this.InitializeComponent();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
WeekID = e.Parameter as string;
AllNews = await NewsItems.Where(News => News.Week == WeekID).ToListAsync();
separateContent();
}
private void separateContent()
{
foreach (News item in AllNews)
{
Debug.WriteLine(item.Tag);
if (item.Tag == "Windows")
Windows.Add(item);
else if (item.Tag == "Apple")
Apple.Add(item);
else if (item.Tag == "Google")
Google.Add(item);
else if (item.Tag == "Other")
Other.Add(item);
else
Top.Add(item);
}
}
private void Tags_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
IntroHead.FontWeight = FontWeights.Normal;
WindowsHead.FontWeight = FontWeights.Normal;
AppleHead.FontWeight = FontWeights.Normal;
GoogleHead.FontWeight = FontWeights.Normal;
OtherHead.FontWeight = FontWeights.Normal;
switch (Tags.SelectedIndex)
{
case 0:
IntroHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(TopNewsPage), Top);
break;
case 1:
WindowsHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Windows);
break;
case 2:
AppleHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Apple);
break;
case 3:
GoogleHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Google);
break;
case 4:
OtherHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Other);
break;
}
}
}
与问题相关的代码行:
StoryContent.Navigate(typeof(TopNewsPage),Top);
这执行得太快了,我想等到之前完成separateContent();
方法 我允许应用程序导航我的XAML布局上的Pivot
控件。如果不这样做,传入(Top
)的参数将为null / empty,我的应用程序将在导航到TopNewsPage
后立即抛出异常。
我该怎么做?
我理解我制作应用程序的方式并不是最好的(MVVM是我将来要探索的东西)但这是我的第一个应用程序而且我真的只想让它工作。我已经用Task
进行了一些探索,但似乎没有任何帮助我的原因,因为Pivot
导航太快了。
答案 0 :(得分:0)
在评论中,您已经提到,在您希望WeekID
工作并Tags_SelectionChanged
设置为WeekID
之前,您主要希望OnNavigatedTo
拥有值。事件。只要Tags_SelectionCHanged
尚未设置,我建议您不要对WeekID
事件做任何事情。
尝试:
private void Tags_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(string.IsNullOrEmpty(WeekID))
return;
IntroHead.FontWeight = FontWeights.Normal;
WindowsHead.FontWeight = FontWeights.Normal;
AppleHead.FontWeight = FontWeights.Normal;
GoogleHead.FontWeight = FontWeights.Normal;
OtherHead.FontWeight = FontWeights.Normal;
switch (Tags.SelectedIndex)
{
case 0:
IntroHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(TopNewsPage), Top);
break;
case 1:
WindowsHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Windows);
break;
case 2:
AppleHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Apple);
break;
case 3:
GoogleHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Google);
break;
case 4:
OtherHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Other);
break;
}
}
如果这适合您,您可能希望在导航到另一个页面之前将事件设置为WeekID
为null或为空,或者当页面关闭时,因为我不知道{{1在此类事件中将保留ContentFrame
的值。只是一个提示。
答案 1 :(得分:0)
注意:我不认为这是解决我的问题的好方法,但它是有效的。
以下是我的所作所为:
Top.Count
中添加了对Tags_SelectionChanged
的检查,以便在List
为空时无法运行。separateContent();
的末尾添加了两行代码,以便在Pivot
包含项目后执行第一个Top
项目。如果您有更好的方法,请分享!
private void separateContent()
{
foreach (News item in AllNews)
{
Debug.WriteLine(item.Tag);
if (item.Tag == "Windows")
Windows.Add(item);
else if (item.Tag == "Apple")
Apple.Add(item);
else if (item.Tag == "Google")
Google.Add(item);
else if (item.Tag == "Other")
Other.Add(item);
else
Top.Add(item);
}
IntroHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(TopNewsPage), Top);
}
private void Tags_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (Top.Count < 6)
return;
IntroHead.FontWeight = FontWeights.Normal;
WindowsHead.FontWeight = FontWeights.Normal;
AppleHead.FontWeight = FontWeights.Normal;
GoogleHead.FontWeight = FontWeights.Normal;
OtherHead.FontWeight = FontWeights.Normal;
switch (Tags.SelectedIndex)
{
case 0:
IntroHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(TopNewsPage), Top);
break;
case 1:
WindowsHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Windows);
break;
case 2:
AppleHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Apple);
break;
case 3:
GoogleHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Google);
break;
case 4:
OtherHead.FontWeight = FontWeights.SemiBold;
StoryContent.Navigate(typeof(OtherNews), Other);
break;
}
}
答案 2 :(得分:0)
TLDR:https://github.com/baskren/P42.Uno.AsyncNavigation/tree/main
要考虑的事情:如果可以预加载页面,则可以异步/等待页面预加载完成,然后再显示它。但是,等等,您说,UWP导航不允许预加载页面-它不是异步/等待!
是的,但是有一种解决方法。首先,请考虑Page
继承自FrameworkElement
。这意味着Page
可以是Grid
的子级,也可以是ContentPresenter
的内容。这是显示此内容的快速实验:
ChildPage.xaml(在展示前我要预加载的页面):
<Page
x:Class="NestedPagesExperiment.Shared.ChildPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:NestedPagesExperiment.Shared"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Page.Content>
<Grid>
<Grid.Children>
<TextBlock Text="I AM THE CHILD PAGE CONTENT!!!!" />
</Grid.Children>
</Grid>
</Page.Content>
</Page>
MainPage.xaml(托管页面-将向其中添加预加载的ChildPage
):
<Page
x:Class="NestedPagesExperiment.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:NestedPagesExperiment"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Content>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.Children>
<TextBlock
Margin="20"
FontSize="30"
Text="Hello, world!" />
<Button
x:Name="_button"
Grid.Row="1"
Click="OnButtonClick"
Content="Add Content" />
<ContentPresenter x:Name="_contentPresenter" Grid.Row="2" />
</Grid.Children>
</Grid>
</Page.Content>
</Page>
MainPage.xaml.cs(后面的代码):
using NestedPagesExperiment.Shared;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace NestedPagesExperiment
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var content = new ChildPage();
_contentPresenter.Content = content;
}
}
}
但是,等一下,您说,我仍然想进行页面转换!看看Xamarin.Forms是如何做到这一点的:
首先,Xamarin有一个页面容器(FormsEmbeddedPageWrapper
),该容器托管着动态生成的页面。
FormsEmbeddedPageWrapper.xaml
<Page
x:Class="Xamarin.Forms.Platform.UWP.FormsEmbeddedPageWrapper"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Xamarin.Forms.Platform.UAP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ContentPresenter Name="Root" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
</ContentPresenter>
</Page>
注意以下几点:
ContentPresenter
,我们将看到,这是放置预加载内容的位置。同样重要的是,看看后面的代码:
public sealed partial class FormsEmbeddedPageWrapper : Windows.UI.Xaml.Controls.Page
{
internal static Dictionary<Guid, ContentPage> Pages = new Dictionary<Guid, ContentPage>();
public FormsEmbeddedPageWrapper()
{
InitializeComponent();
}
protected override void OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Parameter == null)
{
throw new InvalidOperationException($"Cannot navigate to {nameof(FormsEmbeddedPageWrapper)} without "
+ $"providing a {nameof(Xamarin.Forms.Page)} identifier.");
}
// Find the page instance in the dictionary and then discard it so we don't prevent it from being collected
var key = (Guid)e.Parameter;
var page = Pages[key];
Pages.Remove(key);
// Convert that page into a FrameWorkElement we can display in the ContentPresenter
FrameworkElement frameworkElement = page.CreateFrameworkElement();
if (frameworkElement == null)
{
throw new InvalidOperationException($"Could not find or create a renderer for the Page {page}");
}
Root.Content = frameworkElement;
}
}
并且,为了完成谜题,我们还需要一件-一种扩展方法:
internal static bool Navigate(this Windows.UI.Xaml.Controls.Frame frame, ContentPage page, Windows.UI.Xaml.Media.Animation.NavigationTransitionInfo infoOverride)
{
if (page == null)
{
throw new ArgumentNullException(nameof(page));
}
Guid id = Guid.NewGuid();
FormsEmbeddedPageWrapper.Pages.Add(id, page);
if (infoOverride != null)
return frame.Navigate(typeof(FormsEmbeddedPageWrapper), id, infoOverride);
return frame.Navigate(typeof(FormsEmbeddedPageWrapper), id);
}
因此,当需要导航到新页面时,这就是Xamarin.Forms正在做的事情:
FormsEmbeddedPageWrapper.Pages
)中,并键入到新生成的GUID。frame.Navigate(Type, object)
类型和上面生成的GUID密钥作为参数调用UWP FormsEmbeddedPageWrapper
方法。FormsEmbeddedPageWrapper
的新实例。OnNavigatedTo
实例上的UWP调用的FormsEmbeddedPageWrapper
-在参数中包含GUID键。FormsEmbeddedPageWrapper
实例使用GUID键从Pages
静态字典中提取预加载的页面内容。FormsEmbeddedPageWrapper
将其Content
的{{1}}设置为从ContentPresenter
静态字典检索的预加载页面内容。这种方法保留了UWP页面过渡动画的使用,并允许预加载页面内容。
尽管使用Xamarin.Forms代码片段来解释这种方法,但是这种方法没有什么可以在现成的UWP应用中使用的。