我在c ++ / cx XAML应用程序中遇到一个非常奇怪的错误:
我有一个后退按钮,用于检查您所取得的进度是否已保存,以及(如果不是)弹出一个弹出窗口,可让您保存或离开而不保存。但是,在两种情况下都使用this->frame->goBack()
来完成:
当保存进度 时,应用暂停 __debugbreak()
然而,当 goBack()
弹出按钮上的按钮调用,一切正常。为什么会出现这种情况?
该应用程序基于“空白应用程序”模板,页面本身基于Visual Studio 2013提供的“基本页面”模板
BoardPage.xaml
中的控件定义如下:
<AppBarButton x:Name="backButton" Icon="Back" Height="95"
Click="backButton_Clicked">
<AppBarButton.Resources>
<Flyout x:Key="WarningFlyoutBase">
<Grid Height="150" Width="200">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<TextBlock Text="Unsaved progress, what do you want to do?"
HorizontalAlignment="Center" TextWrapping="Wrap"
FontSize="14" Margin="4,10" TextAlignment="Center"/>
<Button x:Name="WarningSaveButton"
Content="Save now."
Grid.Row="1" HorizontalAlignment="Center"
Click="WarningSaveButton_Clicked"/>
<Button x:Name="WarningLeaveButton"
Content="Leave without saving."
Grid.Row="2" HorizontalAlignment="Center"
Click="WarningLeaveButton_Clicked"/>
</Grid>
</Flyout>
</AppBarButton.Resources>
<AppBarButton.Flyout>
<StaticResource ResourceKey="WarningFlyoutBase"/>
</AppBarButton.Flyout>
</AppBarButton>
所以这三个控件(backButton
,WarningSaveButton
和WarningLeaveButton
)都有各自的Clicked事件处理程序,但现在只有两个控件是相关的:
返回按钮:
void Tackle::BoardPage::backButton_Clicked(Platform::Object^ sender,
Windows::UI::Xaml::RoutedEventArgs^ e)
{
if (saved && Frame->CanGoBack) /* saved is a bool */
this->Frame->GoBack();
else
backButton->Flyout->ShowAt((FrameworkElement^)sender);
}
注意:我也尝试将GoBack()
替换为Navigate(TypeName(CreateGamePage::typeid))
,但这没有帮助。
WarningLeaveButton:
void Tackle::BoardPage::WarningLeaveButton_Clicked(Platform::Object^ sender,
Windows::UI::Xaml::RoutedEventArgs^ e)
{
if (Frame->CanGoBack)
this->Frame->GoBack();
}
我试图在很长一段时间内检查这次崩溃/调试的原因,并发现了以下内容:
相关网页已导航至this->Frame->Navigate(TypeName(BoardPage::typeid), ref new CGameSession(job));
。省略第二个参数可以神奇地修复崩溃。
在App.g.hpp
中触发断点时,打开价值errorMessage
的观察值:
“展示位置目标需要位于可视化树中。”
Flyout是如何进入可视化树的,但它附加的Button不是?
NavigationHelper->OnNavigatedTo(e)
方法在最后一行LoadState(this, ref new LoadStateEventArgs(e->Parameter, safe_cast<IMap<String^, Object^>^>(frameState->Lookup(_pageKey))));
失败,因为LoadState()
被调用似乎很奇怪容易且仅包含两个(void)
类型转换。 (我没有修改过这些方法中的任何一种。)答案 0 :(得分:0)
这里的问题在于弹出窗口和事件处理程序与XAML-Controls一起使用的方式,有2个mayor点导致我的代码崩溃:
好吧,当按下backButton
时,backButton_Clicked
会先被触发。
当游戏未保存时,弹出窗口会打开,您可以毫无问题地返回。
但是如果之前保存了游戏 ,事件处理程序会立即调用this->Frame->GoBack()
,它会完全按照它应该做的,构建上一页,加载其状态并绘制它。
但是之后,它会尝试打开弹出窗口,这就是问题:弹出窗口不再存在,因此出现奇怪的错误消息。
我有点尴尬我花了很长时间才想出来,但也许有人会发现这有用,所以我会在这里留下这个问题。
我现在使用的解决方法是将FlyoutBase移动到<Page.Resources>
并将其附加到大小为0x0 px的按钮。然后触发弹出按钮:Flyout::ShowAttachedFlyout(InvisibleButton);