【问题标题】:Cannot bind Icon property in NavigationView MenuItemTemplate无法在 NavigationView MenuItemTemplate 中绑定 Icon 属性
【发布时间】:2018-08-21 15:50:06
【问题描述】:

我尝试使用NavigationView,因为它看起来非常有用,但我正在努力使其与 MVVM 模式一起使用。

我在这个 sn-p 中附加了 MenuItemsSource 属性:

<Page x:Class="App5.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App5"
      ...>

    <Page.DataContext>
        <local:MainViewModel></local:MainViewModel>
    </Page.DataContext>

    <NavigationView MenuItemsSource="{Binding Items}">
        <NavigationView.MenuItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </NavigationView.MenuItemTemplate>
    </NavigationView>
</Page>

我得到的只有这个:

这很酷,但是NavigationViewItem 有一个Icon 属性来装饰文本。

如何根据每个NavigationViewItem绑定的项目设置图标?

注意:我真的不想手动将图标添加为MenuItemTemplate 的一部分,因为这不是应有的方式。我需要的是绑定隐式生成的NavigationViewItems 的 Icon 属性。

问题是怎么做的?

我已经尝试过(使用MenuItemContainerStyle),但它不起作用:

<NavigationView MenuItemsSource="{Binding Items}">
    <NavigationView.MenuItemContainerStyle>
        <Style TargetType="NavigationViewItem">
            <Setter Property="Icon" Value="{Binding Converter={StaticResource ItemToIconConverter}}" />
        </Style>
    </NavigationView.MenuItemContainerStyle>
    <NavigationView.MenuItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </NavigationView.MenuItemTemplate>
</NavigationView>

注意:使用以下答案中建议的 XAML(在 DataTemplate 中放置 NavigationViewItem),NavigationViewItem 在可视树中重复(一个嵌套到另一个):

这不是一个解决方案。此外,它的外观和行为都很糟糕。查看建议解决方案的快照:

【问题讨论】:

    标签: .net mvvm uwp windows-10-universal


    【解决方案1】:

    您声明您不想手动将图标添加为MenuItemTemplate 的一部分,因为它不是人们认为的方式(这是绝对正确的),但实际上您确实做到了设置菜单项的文本也是一样的(手动添加 TextBlock 而不是设置菜单项的 Content 属性)。

    TextBlock 会覆盖任何自动创建的NavigationItemView,因此没有要显示的图标元素(TextBlock 仅包含文本,没有图标)。

    尝试简单地使用NavigationViewItem 作为模板:

    <NavigationView MenuItemsSource="{Binding Items}">
        <NavigationView.MenuItemTemplate>
            <DataTemplate>
                <NavigationViewItem Icon="{Binding Icon}" Content="{Binding Name}"/>
            </DataTemplate>
        </NavigationView.MenuItemTemplate>
    </NavigationView>
    

    【讨论】:

    • 我支持这种方法,像他一样使用 NavigationViewMenuItem。如果您还计划使用分隔符,则可以使用 TemplateSelector 并根据您是否需要 MenuItem 或 Separator 替换 DataTemplate
    • 抱歉,这种方法是一种简单的解决方案。所做的是在NavigationViewItem 内创建一个NavigationViewItem。试试看效果:鼠标悬停点击。如果您的 PC 使用 Fluent Design,您会很欣赏这种重复。
    • 我需要访问隐含的NavigationViewItem,它是由ContainerGenerator 自动生成的。我能想到的唯一方法是在MenuItemContainerStyle 中设置样式。但我认为Styles 内部不支持绑定。
    • 虽然我担心我无法用重复的NavigationViewItem 重现您的视觉问题,但研究表明确实不建议嵌套NavigationViewItems(很抱歉首先给出该建议) ,但官方解决方案似乎“手动”指定图标和文本:social.msdn.microsoft.com/Forums/en-US/…
    • 注意,在 1809 和 17763 SDK 中,您确实可以在数据模板中使用 NavigationViewItem。但是,向下版本只允许 Navigation 视图的 MenuItems 属性中的 NavigationViewItem(不是 MenuItemTemplate)。
    【解决方案2】:

    这让我发疯了!可悲的是,似乎默认行为是将MenuItemTemplate 的内容放在NavigationViewItemContentPresenter 内。

    我解决这个问题的方法是复制NavigationViewItem的默认样式的相关部分,并稍作修改:

    <NavigationView.MenuItemTemplate>
        <DataTemplate>
            <Grid HorizontalAlignment="Left"
                  Height="40"
                  Margin="-16,0,0,0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="48" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Viewbox Grid.Column="0"
                         Margin="16,12">
                    <SymbolIcon Symbol="{x:Bind Icon}" />
                </Viewbox>
                <ContentPresenter Content="{x:Bind Name}"
                                  Grid.Column="1"
                                  VerticalAlignment="Center"/>
            </Grid>
        </DataTemplate>
    </NavigationView.MenuItemTemplate>
    

    修改包括为Grid 设置负边距并添加两个Grid.Column 属性。

    我打开了an issue on the Docs GitHub,希望他们能更好地解释这种行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 2019-09-15
      • 2018-10-09
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 2019-11-30
      相关资源
      最近更新 更多