为什么在框架之间移动页面时页面会消失?
Why does Page disappears when I move it between frames?
我有一个 window 和一个包含页面的 Main 框架。我还有另一个包含第一页的页面。我想在这两个页面之间移动。这是第一页:
第二个:
当我 运行 应用程序时,第一次一切正常。但是当我回到第一页然后回到第二页时,第二页框架中的第一页消失了:
这里是 MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public static TestPage testPage = new TestPage();
public static CombinedPage combinedPage = new CombinedPage();
public MainWindow()
{
InitializeComponent();
}
private void Butt1_Click(object sender, RoutedEventArgs e)
{
combinedPage.TimerFrame.Content = null;
Main.Content = testPage;
}
private void Butt2_Click(object sender, RoutedEventArgs e)
{
Main.Content = null;
combinedPage.Call();
Main.Content = combinedPage;
}
}
MainWindow.xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80 px"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70 px" ></ColumnDefinition>
<ColumnDefinition Width="*" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Left" Grid.RowSpan="2">
<Button x:Name="Butt1" Height="50" Width="50" Click="Butt1_Click" />
<Button x:Name="Butt2" Height="50" Width="50" Click="Butt2_Click" />
</StackPanel>
<Frame NavigationUIVisibility="Hidden" x:Name="Main" Grid.Row="1" Grid.Column="1"/>
</Grid>
CombinedPage.xaml.cs:
public partial class CombinedPage : Page
{
public CombinedPage()
{
InitializeComponent();
}
public void Call()
{
TimerFrame.Content = MainWindow.testPage;
}
}
CombinedPage.xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Grid.RowSpan="3" Width="5" Background="Black"
VerticalAlignment="Stretch" HorizontalAlignment="Center" />
<GridSplitter Grid.Row="1" Grid.ColumnSpan="3" Height="5" Background="Black"
VerticalAlignment="Center" HorizontalAlignment="Stretch" />
<Frame NavigationUIVisibility="Hidden" x:Name="TimerFrame" Grid.Row="0" Grid.Column="0"/>
</Grid>
所以最后一个问题是 - 为什么当我在页面之间移动时第一页消失了?
我实际上很少使用 Frame
静音。这是一个非常重的控件,仅在您要显示网页内容时才推荐使用。
我强烈建议为每个 page/view.
使用 ContentControl
和 DataTemplate
看这个例子:.
使用建议的解决方案可以使导航更加方便。它消除了像你这样的问题。此外,您还有更多选项来自定义页面导航,例如添加动画。
问题是 Frame
实现了特殊的导航流程。设置 Frame.Source
或 Frame.Content
属性 不会立即完成导航,即不会立即应用目的地 Page
值:
(来源:Microsoft Docs: Navigation Overview)
正如您从图表中了解到的那样,设置 Frame.Source
或 Frame.Content
会导致一系列以 LoadCompleted
事件结束的事件。
您当前导航到页面的时间过早。 testPage
仍在最近的 Frame
中加载,因此无法在下一个 Frame
中显示。
您的场景的特殊问题是您希望在不同的 Frame
实例中加载相同的 Page
实例。由于 Page
实例只能渲染一次,所以必须从最近的 Frame
卸载 Page
实例才能在下一个 Frame
.[=43= 中显示它]
要解决您的问题,您有两种选择:
在 null
赋值后处理 LoadCompleted
事件/Frame
重置并从处理程序设置新的 Page
。
使用优先级至少为DispatcherPriority.Background
的Dispatcher
在null
赋值/Frame
重置后延迟赋值。例如:
Dispatcher.InvokeAsync(() => Main.Navigate(testPage), DispatcherPriority.Background);
我建议处理 LoadCompleted
事件,因为该行为绝对更具确定性:
private void Butt1_Click(object sender, RoutedEventArgs e)
{
combinedPage.TimerFrame.LoadCompleted += SetMainFrame_OnLoadCompleted;
combinedPage.TimerFrame.Navigate(null);
}
private void SetMainFrame_OnLoadCompleted(object sender, NavigationEventArgs e)
{
combinedPage.TimerFrame.LoadCompleted -= SetMainFrame_OnLoadCompleted;
Main.Navigate(testPage);
}
private void Butt2_Click(object sender, RoutedEventArgs e)
{
Main.LoadCompleted += SetFrameContents_OnLoadCompleted;
Main.Navigate(null);
}
private void SetFrameContents_OnLoadCompleted(object sender, NavigationEventArgs e)
{
Main.LoadCompleted -= SetFrameContents_OnLoadCompleted;
combinedPage.Call();
Main.Navigate(combinedPage);
}
我有一个 window 和一个包含页面的 Main 框架。我还有另一个包含第一页的页面。我想在这两个页面之间移动。这是第一页:
第二个:
当我 运行 应用程序时,第一次一切正常。但是当我回到第一页然后回到第二页时,第二页框架中的第一页消失了:
这里是 MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public static TestPage testPage = new TestPage();
public static CombinedPage combinedPage = new CombinedPage();
public MainWindow()
{
InitializeComponent();
}
private void Butt1_Click(object sender, RoutedEventArgs e)
{
combinedPage.TimerFrame.Content = null;
Main.Content = testPage;
}
private void Butt2_Click(object sender, RoutedEventArgs e)
{
Main.Content = null;
combinedPage.Call();
Main.Content = combinedPage;
}
}
MainWindow.xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80 px"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70 px" ></ColumnDefinition>
<ColumnDefinition Width="*" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Left" Grid.RowSpan="2">
<Button x:Name="Butt1" Height="50" Width="50" Click="Butt1_Click" />
<Button x:Name="Butt2" Height="50" Width="50" Click="Butt2_Click" />
</StackPanel>
<Frame NavigationUIVisibility="Hidden" x:Name="Main" Grid.Row="1" Grid.Column="1"/>
</Grid>
CombinedPage.xaml.cs:
public partial class CombinedPage : Page
{
public CombinedPage()
{
InitializeComponent();
}
public void Call()
{
TimerFrame.Content = MainWindow.testPage;
}
}
CombinedPage.xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Grid.RowSpan="3" Width="5" Background="Black"
VerticalAlignment="Stretch" HorizontalAlignment="Center" />
<GridSplitter Grid.Row="1" Grid.ColumnSpan="3" Height="5" Background="Black"
VerticalAlignment="Center" HorizontalAlignment="Stretch" />
<Frame NavigationUIVisibility="Hidden" x:Name="TimerFrame" Grid.Row="0" Grid.Column="0"/>
</Grid>
所以最后一个问题是 - 为什么当我在页面之间移动时第一页消失了?
我实际上很少使用 Frame
静音。这是一个非常重的控件,仅在您要显示网页内容时才推荐使用。
我强烈建议为每个 page/view.
使用 ContentControl
和 DataTemplate
看这个例子:
使用建议的解决方案可以使导航更加方便。它消除了像你这样的问题。此外,您还有更多选项来自定义页面导航,例如添加动画。
问题是 Frame
实现了特殊的导航流程。设置 Frame.Source
或 Frame.Content
属性 不会立即完成导航,即不会立即应用目的地 Page
值:
正如您从图表中了解到的那样,设置 Frame.Source
或 Frame.Content
会导致一系列以 LoadCompleted
事件结束的事件。
您当前导航到页面的时间过早。 testPage
仍在最近的 Frame
中加载,因此无法在下一个 Frame
中显示。
您的场景的特殊问题是您希望在不同的 Frame
实例中加载相同的 Page
实例。由于 Page
实例只能渲染一次,所以必须从最近的 Frame
卸载 Page
实例才能在下一个 Frame
.[=43= 中显示它]
要解决您的问题,您有两种选择:
在
null
赋值后处理LoadCompleted
事件/Frame
重置并从处理程序设置新的Page
。使用优先级至少为
DispatcherPriority.Background
的Dispatcher
在null
赋值/Frame
重置后延迟赋值。例如:Dispatcher.InvokeAsync(() => Main.Navigate(testPage), DispatcherPriority.Background);
我建议处理 LoadCompleted
事件,因为该行为绝对更具确定性:
private void Butt1_Click(object sender, RoutedEventArgs e)
{
combinedPage.TimerFrame.LoadCompleted += SetMainFrame_OnLoadCompleted;
combinedPage.TimerFrame.Navigate(null);
}
private void SetMainFrame_OnLoadCompleted(object sender, NavigationEventArgs e)
{
combinedPage.TimerFrame.LoadCompleted -= SetMainFrame_OnLoadCompleted;
Main.Navigate(testPage);
}
private void Butt2_Click(object sender, RoutedEventArgs e)
{
Main.LoadCompleted += SetFrameContents_OnLoadCompleted;
Main.Navigate(null);
}
private void SetFrameContents_OnLoadCompleted(object sender, NavigationEventArgs e)
{
Main.LoadCompleted -= SetFrameContents_OnLoadCompleted;
combinedPage.Call();
Main.Navigate(combinedPage);
}