我有一个带有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
结果看起来像这样,项目的内容设置为等于网格的内容:
这正是我所需要的,但是我不知道如何将项目的IsEnabled属性绑定到NavigationViewElement.IsItemEnabled。
当我尝试遵循建议的模型时,将NavigationViewItem添加到DataTemplate中是这样的:
NavigationViewItem
然后我可以根据需要绑定IsEnabled属性,但是UI无法正确绘制。该项目的内容似乎在我已经拥有的项目之上添加了第二个NavigationViewItem。单击带有文本的区域没有任何作用-我必须单击浅灰色区域之外的项目才能进行导航。
对我在做什么的任何见解?总之,我希望找到一种既可以自定义NavigationViewItem的显示内容,又可以将IsEnabled属性绑定到模型中NavigationViewElement上的属性的方法。
答案 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>");
}
更新一个
问题的关键在于我们无法在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