我正在用 C++ 开发一个动态生成 UI 的跨平台项目,我在使用 C++/winRT UWP NavigationView 的两个问题上苦苦挣扎:
- 定义 NavigationViewItemHeader 时,生成的标题标题不会显示在导航菜单中,空间保持空白,
- 尝试更新导航菜单的 SettingsItem 时,设置导航项的值为 SettingsItem() 返回的 nullptr。
这是我编写的代码,用于从独立于主机(例如 Windows)管理的项目列表中生成菜单:
bool
CANavigationView::UpdateHostView( void )
{
TNavigationItemPtr item;
TIndex index;
if( _hostViewUpdateNeeded == false )
return false;
Windows::UI::Xaml::Controls::NavigationViewItemBase hItem( nullptr );
Windows::UI::Xaml::Controls::TextBlock hText( nullptr );
winrt::hstring hTag;
// Remove all navigation items from the current host view:
_hostNavigationView.MenuItems().Clear();
_hostNavigationView.IsSettingsVisible( false );
// Build the navigation menu items:
for( index = 0; index < _navigationItems.CountOfItems(); index++ )
{
item = * _navigationItems.GetItemAtIndex( index );
if( item->identifier == kSettingsItem )
{
_hostNavigationView.IsSettingsVisible( true );
hText = Windows::UI::Xaml::Controls::TextBlock();
CSString::ConvertToUIString( item->title->GetString( gAppLanguageCode ), & hTag );
hText.Text( hTag );
// Issue #1 : cannot access to the Settings item
// _hostNavigationView.SettingsItem().as< Windows::UI::Xaml::Controls::NavigationViewItem >().Content( hText );
// SettingsItem() returns nullptr...
}
else
{
switch( item->type )
{
case eNavigationHeader:
hItem = Windows::UI::Xaml::Controls::NavigationViewItemHeader();
hText = Windows::UI::Xaml::Controls::TextBlock();
CSString::ConvertToUIString( item->title->GetString( gAppLanguageCode ), & hTag );
hText.Text( hTag );
// Issue #2: The header's title is not displayed
hItem.Content( hText );
_hostNavigationView.MenuItems().Append( hItem );
break;
case eNavigationSeparator:
hItem = Windows::UI::Xaml::Controls::NavigationViewItemSeparator();
_hostNavigationView.MenuItems().Append( hItem );
break;
case eNavigationItem:
hItem = Windows::UI::Xaml::Controls::NavigationViewItem();
CSString::ConvertToUIString( CAUIElement::GetStringFromUIIdentifier( item->identifier ), & hTag );
hItem.Tag( winrt::box_value( hTag ) );
hText = Windows::UI::Xaml::Controls::TextBlock();
CSString::ConvertToUIString( item->title->GetString( gAppLanguageCode ), & hTag );
hText.Text( hTag );
hItem.Content( hText );
hItem.as< Windows::UI::Xaml::Controls::NavigationViewItem>().Icon( GetHostIcon( item->icon ) );
_hostNavigationView.MenuItems().Append( hItem );
break;
default:
break;
}
}
}
_hostViewUpdateNeeded = false;
return true;
}
因为我使用自己的字符串格式(我坚持使用旧的 C++ 标准...)和 I18N 支持,所以我需要先将 UTF8 字符串转换为主机(此处为 Windows),然后再设置文本 block ,使用 hstring 类型的 hTag 变量。在 Debug模式下,文本很好地转码为hstring格式...
令我困惑的是,NavigationSeparator 和 NavigationItem 案例都工作正常,符合 Microsoft 官方文档(包括用于菜单事件处理的 Tag 和 NavigationViewItem 的图标设置)。
我知道这不是在 UWP 用户界面上工作的“主流 XAML 方式”,但到目前为止,该方法在其他 UI 元素上运行良好。
这是带有标题空白区域的导航 View 的屏幕截图:
此外,在上面的示例中,我记录了主机导航 View (_hostNavigationView.MenuItems().Size()) 中菜单项的数量,结果是 7,这是正确的...
最后,这是我在 DEBUG 模式下生成的详细日志:
DBG-[000002686A230710]CANavigationView::UpdateDisplayedLanguage() {
DBG-[000002686A230710]CANavigationView::UpdateHostView() {
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item 0, type 2
DBG-[000002686A230710]CANavigationView::UpdateHostView() Header case: Reference Library
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item 1, type 1
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item case
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item 2, type 1
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item case
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item 3, type 1
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item case
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item 4, type 3
DBG-[000002686A230710]CANavigationView::UpdateHostView() Separator case
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item 5, type 2
DBG-[000002686A230710]CANavigationView::UpdateHostView() Header case: Project Library
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item 6, type 1
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item case
DBG-[000002686A230710]CANavigationView::UpdateHostView() Navigation item 7, type 1
DBG-[000002686A230710]CANavigationView::UpdateHostView() Settings case
DBG-[000002686A230710]CANavigationView::UpdateHostView() Value of SettingsItem(): 0000000000000000
DBG-[000002686A230710]CANavigationView::UpdateHostView() Count of menu items for the navigation view: 7 (8)
DBG-}
DBG-}
非常感谢您帮助解决这两个问题!
最好的问候,
阿诺
最佳答案
根据 Roy 的评论,没有必要使用 TextBlock 来设置 NavigationViewItemHeader 和 NavigationViewItem 的值。相反,它只是将字符串值装箱到 IInspectable 对象中的一种情况:
hItem.Content( winrt::box_value( hTag ) );
现在,我有了正确的导航菜单显示和行为:
谢谢你,罗伊!
更新: 我还设法更改了 SettingsItem 的标题。根据文档,自定义导航菜单的好时机是在加载 View 时。
因此,我订阅/注册了 Loaded() 事件并从那里执行了自定义。在导航 View 生命周期的那个阶段,SettingsItem() 返回一个有效的 NavigationViewItem,允许我使用相同的字符串装箱方法更改标题。
现在两个问题都解决了!
关于c++ - 如何使用 C++/winRT 动态定义 UWP NavigationView 菜单的标题和设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70944049/