Enable/Disable C# WPF NavigationView 控件中的子菜单项
Enable/Disable sub-menu item within C# WPF NavigationView control
我有一个 C# WPF 应用程序,它使用 NavigationView 控件来提供菜单树。我想根据应用程序的状态 enable/disable 菜单中的项目。
我的NavigationView在xaml中声明如下
MyApp.xaml
<Window.Resources>
<!-- Simple data template for navigation menu items -->
<DataTemplate x:Key="NavigationViewMenuItem">
<ui:NavigationViewItem
Content="{Binding Title}"
Icon="{Binding Icon}"
SelectsOnInvoked="{Binding Selectable}"
FontWeight="{Binding Selectable, Converter={x:Static cnv:FontConverters.FontWeight}}"
MenuItemsSource="{Binding Children}"/>
</DataTemplate>
<SolidColorBrush x:Key="NavigationViewItemForegroundSelected" Color="{StaticResource CoralMagentaLight2}"/>
<SolidColorBrush x:Key="NavigationViewItemForegroundSelectedPointerOver" Color="{StaticResource CoralMagentaLight2}"/>
<SolidColorBrush x:Key="NavigationViewItemForegroundSelectedPressed" Color="{StaticResource CoralMagentaLight2}"/>
</Window.Resources>
<ui:NavigationView
x:Name="NavigationView"
IsBackButtonVisible="Collapsed"
MenuItemTemplate="{StaticResource NavigationViewMenuItem}"
PaneDisplayMode="Auto"
md:ShadowAssist.ShadowEdges="Right">
控件绑定到视图模型上的列表
MyApp.xaml.cs
this.OneWayBind(ViewModel, vm => vm.MenuItems, v => v.NavigationView.MenuItemsSource)
.DisposeWith(disposables);
MyViewModel.cs
[Reactive]
public List<MenuItemModel> MenuItems { get; set; } = NavigationHelper.NavigationHierarchy;
我提供了一种方法来更改给定项目的可选状态,如下所示
public void SetMenuItemState(string title, bool enabled)
{
var item = MenuItems.Where(x => x.Title == title).First();
if (item != null)
{
if (item.Selectable != enabled)
{
item.Selectable = enabled;
// Required to completely re-assign the MenuItems for
// the change to take affect.
MenuItems = NavigationHelper.EmptyHierarchy;
MenuItems = items;
}
}
}
我想避免必须更新整个列表以使更改生效,并通过原位更改菜单项状态,如下所示,但这不起作用。
public void SetMenuItemState(string title, bool enabled)
{
var items = MenuItems;
var item = MenuItems.Where(x => x.Title == title).First();
if (item != null)
{
int index = MenuItems.IndexOf(item);
MenuItems[index].Selectable = enabled;
}
}
我尝试制作菜单项列表和可观察集合,但这没有任何区别。如果有人可以建议 disable/enable 一个菜单项而不必重新分配整个列表的方法,我将不胜感激。
一个解决办法就是改变
List<MenuItemModel>
至
ObservableCollection<MenuItemModel>
并实现对 Selectable 属性 的更改,如下所示。
static public void SetMenuItemState(ref ObservableCollection<MenuItemModel> menuItems, string title, bool enabled)
{
var item = menuItems.Where(x => x.Title == title).FirstOrDefault();
if (item != null)
{
int index = menuItems.IndexOf(item);
if (item.Selectable != enabled)
{
item.Selectable = enabled;
menuItems[index] = item;
}
}
}
您的 MenuItemModel
应该实施 INotifyPropertyChanged
并为 Selectable
引发 PropertyChanged
事件 属性:
public class MenuItemModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int _selectable;
public bool Selectable
{
get { return _selectable; }
set { _selectable = value; NotifyPropertyChanged(); }
}
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
...
}
那么您的原始代码应该可以工作。没有理由 re-set menuItems[index]
或切换到 ObservableCollection<T>
.
我有一个 C# WPF 应用程序,它使用 NavigationView 控件来提供菜单树。我想根据应用程序的状态 enable/disable 菜单中的项目。
我的NavigationView在xaml中声明如下
MyApp.xaml
<Window.Resources>
<!-- Simple data template for navigation menu items -->
<DataTemplate x:Key="NavigationViewMenuItem">
<ui:NavigationViewItem
Content="{Binding Title}"
Icon="{Binding Icon}"
SelectsOnInvoked="{Binding Selectable}"
FontWeight="{Binding Selectable, Converter={x:Static cnv:FontConverters.FontWeight}}"
MenuItemsSource="{Binding Children}"/>
</DataTemplate>
<SolidColorBrush x:Key="NavigationViewItemForegroundSelected" Color="{StaticResource CoralMagentaLight2}"/>
<SolidColorBrush x:Key="NavigationViewItemForegroundSelectedPointerOver" Color="{StaticResource CoralMagentaLight2}"/>
<SolidColorBrush x:Key="NavigationViewItemForegroundSelectedPressed" Color="{StaticResource CoralMagentaLight2}"/>
</Window.Resources>
<ui:NavigationView
x:Name="NavigationView"
IsBackButtonVisible="Collapsed"
MenuItemTemplate="{StaticResource NavigationViewMenuItem}"
PaneDisplayMode="Auto"
md:ShadowAssist.ShadowEdges="Right">
控件绑定到视图模型上的列表
MyApp.xaml.cs
this.OneWayBind(ViewModel, vm => vm.MenuItems, v => v.NavigationView.MenuItemsSource)
.DisposeWith(disposables);
MyViewModel.cs
[Reactive]
public List<MenuItemModel> MenuItems { get; set; } = NavigationHelper.NavigationHierarchy;
我提供了一种方法来更改给定项目的可选状态,如下所示
public void SetMenuItemState(string title, bool enabled)
{
var item = MenuItems.Where(x => x.Title == title).First();
if (item != null)
{
if (item.Selectable != enabled)
{
item.Selectable = enabled;
// Required to completely re-assign the MenuItems for
// the change to take affect.
MenuItems = NavigationHelper.EmptyHierarchy;
MenuItems = items;
}
}
}
我想避免必须更新整个列表以使更改生效,并通过原位更改菜单项状态,如下所示,但这不起作用。
public void SetMenuItemState(string title, bool enabled)
{
var items = MenuItems;
var item = MenuItems.Where(x => x.Title == title).First();
if (item != null)
{
int index = MenuItems.IndexOf(item);
MenuItems[index].Selectable = enabled;
}
}
我尝试制作菜单项列表和可观察集合,但这没有任何区别。如果有人可以建议 disable/enable 一个菜单项而不必重新分配整个列表的方法,我将不胜感激。
一个解决办法就是改变
List<MenuItemModel>
至
ObservableCollection<MenuItemModel>
并实现对 Selectable 属性 的更改,如下所示。
static public void SetMenuItemState(ref ObservableCollection<MenuItemModel> menuItems, string title, bool enabled)
{
var item = menuItems.Where(x => x.Title == title).FirstOrDefault();
if (item != null)
{
int index = menuItems.IndexOf(item);
if (item.Selectable != enabled)
{
item.Selectable = enabled;
menuItems[index] = item;
}
}
}
您的 MenuItemModel
应该实施 INotifyPropertyChanged
并为 Selectable
引发 PropertyChanged
事件 属性:
public class MenuItemModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int _selectable;
public bool Selectable
{
get { return _selectable; }
set { _selectable = value; NotifyPropertyChanged(); }
}
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
...
}
那么您的原始代码应该可以工作。没有理由 re-set menuItems[index]
或切换到 ObservableCollection<T>
.