【问题标题】:How to mix dynamic and static items in UWP XAML NavigationView MenuItems?如何在 UWP XAML NavigationView MenuItems 中混合动态和静态项?
【发布时间】:2018-04-04 17:14:13
【问题描述】:

我正在尝试制作 NavigationViewMenu,我需要一个布局如下的菜单

  • 静态主页项

  • 静态标题

  • 来自数据库的动态元素作为项目

  • 静态标题

  • 静态项目集

这是我尝试过的:

<NavigationView.MenuItems>

    <NavigationViewItem Icon="Home"  Content="Home" Tag="home" />

    <NavigationViewItemSeparator />

    <NavigationViewItemHeader Content="My Stuff"/>

    <NavigationViewList ItemsSource="{x:Bind MyStuff}">
        <NavigationViewList.ItemTemplate>
            <DataTemplate x:DataType="local:MyModel">
                <NavigationViewItem Icon="Pictures" Content="{x:Bind Name}" Tag="{x:Bind Tag}" />
            </DataTemplate>
        </NavigationViewList.ItemTemplate>
    </NavigationViewList>

    <!-- Static equivalent to the above:
    <NavigationViewItem Icon="Pictures" Content="Woop" Tag="foos"/>
    <NavigationViewItem Icon="Pictures" Content="Doop" Tag="foos"/>
    <NavigationViewItem Icon="Pictures" Content="Loop" Tag="foos"/>
    -->

    <NavigationViewItemHeader Content="Other Stuff"/>

    <NavigationViewItem Icon="Pictures" Content="Foos" Tag="foos"/>
    <NavigationViewItem Icon="ContactInfo" Content="Bars" Tag="bars"/>
    <NavigationViewItem Icon="SwitchApps" Content="Bazes" Tag="bazes"/>

</NavigationView.MenuItems>

这就是我所拥有的:

这就是我想要的:

在 UWP 的 XAML 中,有没有像 Angular 的 *ngFor 一样好的和实用的东西?

【问题讨论】:

标签: xaml uwp uwp-xaml creators-update


【解决方案1】:

我可以复制它。当将自己放入 NavigationView.MenuItem 时,看起来 NavigationViewList 只占用一项的空间。这就像将 ListView 放在 ListViewItem 中一样。要更改此行为,我们需要自己更改项目的行为。然而,经过一些调查,目前 NavigationViewList 的定制似乎对我们来说是黑盒。所以我能想到的唯一方法就是在 splitview 和 acryc 的帮助下构建我们自己的 NavigationView。

【讨论】:

  • 我可能会用这个,看起来像一个带有列表视图和按钮的丙烯酸容器会整理出来,尽管很麻烦,但失去了 NavigationView 酷撤回并实现了响应性
【解决方案2】:

我遇到了同样的行为,并设法找到了解决方法。就我而言,我有两个菜单项列表(动态数据绑定项),我想在两者(静态项)之上使用NavigationViewItemHeader。我尝试使用NavigationViewList 并遇到了您的问题。

TL;DR:

在 C# 代码中创建菜单项列表。此列表的元素可以是您的视图模型和任何静态导航项(标题、分隔符等)的混合。然后使用 DataTemplateSelector 将数据绑定到您的视图模型或传递未更改的导航项。

更详细

在您的 C# 代码隐藏中,为您的菜单项创建一个可枚举(或可观察的集合)。在我的例子中,SomeCollectionAnotherCollection 代表我想要绑定到我的 NavigationView 的数据源。我必须将其键入为object,因为它混合了我的视图模型和内置的 UWP 导航项类型。

private IEnumerable<object> MenuItems()
{
    yield return new NavigationViewItemHeader { Content = "Some List" };
    foreach (var some in SomeCollection)
    {
        yield return some;
    }
    yield return new NavigationViewItemHeader { Content = "Another List" };
    foreach (var another in AnotherCollection)
    {
        yield return another;
    }
}

// somewhere else, like in your Page constructor or a CollectionChanged handler
this.NavigationList = MenuItems().ToList();

其次,创建一个数据模板选择器来在你的模板和导航项之间切换:

class NavigationItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate ViewModelTemplate{ get; set; }
    public DataTemplate NavigationItemTemplate { get; set; }
    protected override DataTemplate SelectTemplateCore(object item)
    {
        return item is MyViewModel
            ? ViewModelTemplate
            : NavigationItemTemplate;
    }
}

最后,更改您的NavigationView 以引用模板选择器和菜单项源。 NavigationItemTemplate 只是一个传递,您的 ViewModelTemplate 将具有正常的视图模型项绑定逻辑。

<Page.Resources>
    <DataTemplate x:Key="ViewModelTemplate" x:DataType="local:MyViewModel">
        <TextBlock Text="{x:Bind SomeProperty}" />
    </DataTemplate>
    <DataTemplate x:Key="NavigationItemTemplate">
    </DataTemplate>
    <local:NavigationItemTemplateSelector x:Key="NavigationItemTemplateSelector"
        ViewModelTemplate="{StaticResource ViewModelTemplate}"
        NavigationItemTemplate="{StaticResource NavigationItemTemplate}" />
</Page.Resources>


<NavigationView
    MenuItemsSource="{x:Bind NavigationList, Mode=OneWay}"
    MenuItemTemplateSelector="{StaticResource NavigationItemTemplateSelector}">
    <Frame x:Name="ContentFrame"></Frame>
</NavigationView>

【讨论】:

    【解决方案3】:

    我发现没有必要像接受的答案那样使用不同的模板,可能是因为同时底层 Windows 代码发生了一些变化。由于我需要菜单的稳定部分,然后根据实际页面需要动态部分,因此我创建了一个界面:

    interface IMenuProvider {
      IEnumerable<NavigationViewItemBase> GetMenuItems();
    }
    

    并确保我的所有页面都实现了它。我的MainPage返回固定部分:

    public IEnumerable<NavigationViewItemBase> GetMenuItems() {
      yield return new NavigationViewItem {
        Tag = "home",
        Icon = new SymbolIcon(Symbol.Home),
        Content = "Home",
      };
      yield return new NavigationViewItemSeparator();
      yield return new NavigationViewItem {
        Tag = "xxx",
        Icon = new SymbolIcon(Symbol.XXX),
        Content = "XXX",
      };
    }
    

    其他页面也提供自己的菜单标题和项目。

    当我浏览页面时,我也会更改菜单,将固定部分和可变部分连接起来:

    ContentFrame.Navigate(PageType, null, transitionInfo);
    if (ContentFrame.Content is IMenuProvider menuProvider)
      = GetMenuItems().Concat(menuProvider.GetMenuItems()).ToList();
    

    (或者,您可以将菜单更改放入FrameNavigated 处理程序中。)

    虽然这些菜单(至少是固定部分)不能在 XAML 中声明仍然很麻烦,但这种方法是可行的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 1970-01-01
      • 2018-04-14
      • 1970-01-01
      • 2019-03-28
      相关资源
      最近更新 更多