UWP-在NavigationViewItems上设置IsEnabled

时间:2018-12-27 23:25:20

标签: c# uwp uwp-xaml

我有一个带有NavigationView控件的UWP应用。通过将XAML中的MenuItemsSource设置为NavigationViewElement类型的对象集合来创建导航项。

<NavigationView 
        Style="{StaticResource MainPageNavControlStyle}" 
        HeaderTemplate="{StaticResource MainPageNavHeaderTemplate}"
        MenuItemsSource="{Binding NavigationViewElements}"
        MenuItemContainerStyleSelector="{StaticResource NavStyleSelector}"
        MenuItemTemplateSelector="{StaticResource NavItemTemplateSelector}"
        x:Name="NavigationViewControl" 
        CompactModeThresholdWidth="480" 
        ExpandedModeThresholdWidth="635" 
        OpenPaneLength="324"
        Loaded="OnControlLoaded"
        ItemInvoked="OnItemInvoked"
        IsTabStop="False"
        IsSettingsVisible="False"
>

我想将创建的IsEnabled的{​​{1}}属性绑定到NavigationViewItems上的属性。我该怎么办?

我对NavigationViewElement也有类似的疑问。在那种情况下,我能够从ListBox派生一个新类,该类重写ListBox并根据绑定到的类中的数据设置PrepareContainerForItemOverride()的{​​{1}}标志( OptionItem,在这种情况下)

IsEnabled

是否有ListBoxItem的等效项?还是有其他方法表明protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item) { ListBoxItem lItem = element as ListBoxItem; OptionItem oItem = item as OptionItem; if (lItem != null && oItem != null) { lItem.IsEnabled = oItem.IsEnabled; } base.PrepareContainerForItemOverride(element, item); } 的{​​{1}}标志应绑定到NavigationView?

更新 我看了Nico Zhu提出的解决方案,但不确定如何将其应用于我的要求。那可能是由于我对XAML的经验不足。

在我的实现中,由于我的布局要求,我从Selector对象引用的DataTemplates不包含NavigationViewItem元素。我不是简单地设置NavigationViewItem.Content和.Glyph,而是使用一堆控件填充Grid。这是一个示例:

IsEnabled

结果看起来像这样,项目的内容设置为等于网格的内容:

enter image description here

这正是我所需要的,但是我不知道如何将项目的IsEnabled属性绑定到NavigationViewElement.IsItemEnabled。

当我尝试遵循建议的模型时,将NavigationViewItem添加到DataTemplate中是这样的:

NavigationViewItem

然后我可以根据需要绑定IsEnabled属性,但是UI无法正确绘制。该项目的内容似乎在我已经拥有的项目之上添加了第二个NavigationViewItem。单击带有文本的区域没有任何作用-我必须单击浅灰色区域之外的项目才能进行导航。

enter image description here

对我在做什么的任何见解?总之,我希望找到一种既可以自定义NavigationViewItem的显示内容,又可以将IsEnabled属性绑定到模型中NavigationViewElement上的属性的方法。

2 个答案:

答案 0 :(得分:3)

要将MenuItemsSource与模型绑定,可以参考official code sample。在最新版本中,我们添加了有关为MenuItemsSource设置数据源的新功能。如果要启用或禁用NavigationViewItem,可以在模型中设置IsEnabled属性,然后将其绑定。请检查以下代码。

Xaml代码

<Page.Resources>
    <local:MenuItemTemplateSelector x:Key="selector">
        <local:MenuItemTemplateSelector.ItemTemplate>
            <DataTemplate x:DataType="local:Category" >
                <NavigationViewItem Content="{x:Bind Name}" 
                                    ToolTipService.ToolTip="{x:Bind Tooltip}" 
                                    IsEnabled="{x:Bind IsEnabled}" >
                    <NavigationViewItem.Icon>
                        <SymbolIcon Symbol="{x:Bind Glyph}" />
                    </NavigationViewItem.Icon>
                </NavigationViewItem>
            </DataTemplate>
        </local:MenuItemTemplateSelector.ItemTemplate >
    </local:MenuItemTemplateSelector>
</Page.Resources>
<Grid>
    <NavigationView x:Name="nvSample" 
            MenuItemTemplateSelector="{StaticResource selector}"                      
            MenuItemsSource="{x:Bind Categories, Mode=OneWay}" />

</Grid>

隐藏代码

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        Categories = new ObservableCollection<CategoryBase>();
        Categories.Add(new Category { Name = "Category 1", Glyph = Symbol.Home, Tooltip = "This is category 1", IsEnabled = false });
        Categories.Add(new Category { Name = "Category 2", Glyph = Symbol.Keyboard, Tooltip = "This is category 2", IsEnabled = true });
        Categories.Add(new Category { Name = "Category 3", Glyph = Symbol.Library, Tooltip = "This is category 3" , IsEnabled = false });
        Categories.Add(new Category { Name = "Category 4", Glyph = Symbol.Mail, Tooltip = "This is category 4", IsEnabled = true });
    }

    public ObservableCollection<CategoryBase> Categories { get;  set; }
}


public class CategoryBase { }

public class Category : CategoryBase
{
    public string Name { get; set; }
    public string Tooltip { get; set; }
    public Symbol Glyph { get; set; }
    public bool IsEnabled { get; set; }
}

public class Separator : CategoryBase { }

public class Header : CategoryBase
{
    public string Name { get; set; }
}

[ContentProperty(Name = "ItemTemplate")]
class MenuItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate ItemTemplate { get; set; }
    protected override DataTemplate SelectTemplateCore(object item)
    {
        return item is Separator ? SeparatorTemplate : item is Header ? HeaderTemplate : ItemTemplate;
    }
    internal DataTemplate HeaderTemplate = (DataTemplate)XamlReader.Load(
       @"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>
               <NavigationViewItemHeader Content='{Binding Name}' />
              </DataTemplate>");

    internal DataTemplate SeparatorTemplate = (DataTemplate)XamlReader.Load(
        @"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>
                <NavigationViewItemSeparator />
              </DataTemplate>");
}

enter image description here



更新一个

问题的关键在于我们无法在1803年使用DataTemplate。通常,为了在1803年创建NavigationViewItem,我们经常使用以下解决方案。

Xaml

<NavigationView x:Name="nvSample" MenuItemsSource="{x:Bind NavItems}" >

</NavigationView>

背后的代码

public ObservableCollection<Category> Categories { get; set; }
public MainPage()
{
    this.InitializeComponent();
    Categories = new ObservableCollection<Category>();
    Categories.Add(new Category { Name = "Category 1", Glyph = Symbol.Home, Tooltip = "This is category 1", IsEnabled = false });
    Categories.Add(new Category { Name = "Category 2", Glyph = Symbol.Keyboard, Tooltip = "This is category 2", IsEnabled = true });
    Categories.Add(new Category { Name = "Category 3", Glyph = Symbol.Library, Tooltip = "This is category 3", IsEnabled = true });
    Categories.Add(new Category { Name = "Category 4", Glyph = Symbol.Mail, Tooltip = "This is category 4", IsEnabled = true });

}
public IEnumerable<NavigationViewItemBase> NavItems
{
    get
    {
        return Categories.Select(
               b => (new NavigationViewItem
               {
                   Content = b.Name,
                   Icon = new SymbolIcon(b.Glyph),
                   IsEnabled = b.IsEnabled,
               })
        );
    }
}

简而言之,我们需要将数据模型转换为NavigationViewItem。但不要在1803年内使用DataTemplate。请尝试此操作。有关更多详细信息,您也可以参考此case

答案 1 :(得分:0)

如果可以使用1809,则该行为允许您按照当前的方式在DataTemplate中使用NavigationViewItems。

但是,在向下版本中,NavigationViewItem仅在MenuItems属性中被允许,而不能在MenuItemTemplate属性中使用。因此,您可以在没有DataTemplate的情况下将项目移动到MenuItems属性。

如果您使用的是降级版本,并且想将MenuItemTemplate属性与DataTemplate一起使用,则需要使用NavigationViewItem以外的其他功能。例如,您可以使用Button.Content设置为网格的按钮。在网格内,您可以包括SymbolIcon和TextBlock之类的东西。需要进行一些工作才能正确设置格式。

我的建议是,如果您需要使用1803,请将NavigationViewItems移到NavigationView本身的MenuItems属性。

有关文档,请参见:https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationviewitem