UWP - setting IsEnabled on NavigationViewItems

独自空忆成欢 提交于 2019-12-03 16:01:21

For binding MenuItemsSource with model, you could refer official code sample. In latest version we have added new feature about setting datasource for MenuItemsSource. If you want to enable or disable NavigationViewItem, you could make IsEnabled property in the model then bind it. Please check the following code.

Xaml Code

<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>

Code Behind

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>");
}



Update One

The key to the problem is that we can’t use DataTemplate in 1803. In general, for creating NavigationViewItem in 1803 we often use the following solution.

Xaml

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

</NavigationView>

Code behind

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,
               })
        );
    }
}

In short, we need convert Data Model to NavigationViewItem. But not using DataTemplate within 1803. Please try this. For more detail you could also refer this case.

If you can use 1809, the behavior there allows NavigationViewItems in a DataTemplate as you are currently doing.

In down-versions however, NavigationViewItem was only allowed in the MenuItems property and could not be used in the MenuItemTemplate property. So, you could move your items to the MenuItems property without a DataTemplate.

If you're on a down-version and you want to use the MenuItemTemplate property with a DataTemplate, you'll need to use something other than NavigationViewItem. For example, you could use a button with the Button.Content set to a grid. Within the grid, you could include something like a SymbolIcon and TextBlock. It would take some work to get the formatting right.

My suggestion is, if you need to use 1803, move the NavigationViewItems to the MenuItems property of the NavigationView itself.

For documentation, please see: https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationviewitem

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!