c++ - 如何使用 C++/winRT 动态定义 UWP NavigationView 菜单的标题和设置?

标签 c++ user-interface uwp c++-winrt

我正在用 C++ 开发一个动态生成 UI 的跨平台项目,我在使用 C++/winRT UWP NavigationView 的两个问题上苦苦挣扎:

  1. 定义 NavigationViewItemHeader 时,生成的标题标题不会显示在导航菜单中,空间保持空白,
  2. 尝试更新导航菜单的 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 的屏幕截图:

Actual NavigationView

此外,在上面的示例中,我记录了主机导航 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 ) );

现在,我有了正确的导航菜单显示和行为:

enter image description here

谢谢你,罗伊!

更新: 我还设法更改了 SettingsItem 的标题。根据文档,自定义导航菜单的好时机是在加载 View 时。

因此,我订阅/注册了 Loaded() 事件并从那里执行了自定义。在导航 View 生命周期的那个阶段,SettingsItem() 返回一个有效的 NavigationViewItem,允许我使用相同的字符串装箱方法更改标题。

现在两个问题都解决了!

关于c++ - 如何使用 C++/winRT 动态定义 UWP NavigationView 菜单的标题和设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70944049/

相关文章:

c++ - Extern 用于全局和静态全局变量

c++ - QXcbIntegration : Cannot create platform OpenGL context, GLX 和 EGL 均未启用

c++ - 在 C++ 中创建返回 int 数组的可执行文件

xaml - UWP xaml : How to display a button with icon and text in it?

c# - 更改 InkToolbar 的颜色 [UWP]

c# - 0x8007007E 仅在 Windows Phone 目标中

c++ - 什么是 G_STMT_START 和 G_STMT_END?

java - System.out.println 到 JTextArea

java - 使用 Java 创建 Snake

java - 如何让JButton出现文字?