c# - 尝试根据另一个 ComboBox 值将绑定的 ObservableCollection 过滤到组合框不起作用
问题描述
我看到了其他几篇关于此的帖子,但我似乎无法确切了解如何使其正常工作以供我使用。
简而言之,这就是我所拥有的。
我有两个组合框——角色和位置。
我将这两个绑定到一个 ObservableCollection,它在实例化时将枚举值转换为加载到其中的字符串。
<ComboBox x:Name="empRoleCB" ItemsSource="{Binding Role}" SelectedItem="{Binding RoleStr}"/>
<ComboBox x:Name="empPositionCB" ItemsSource="{Binding Pos}" SelectedItem="{Binding PosStr}"/>
在我的视图模型中:
public abstract class EmployeeMenuVMBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if(!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
return false;
}
}
class EmployeeMenuVM : EmployeeMenuVMBase
{
private ObservableCollection<string> _pos = new ObservableCollection<string>(Enum.GetNames(typeof(Global.Positions)));
private ObservableCollection<string> _role = new ObservableCollection<string>(Enum.GetNames(typeof(Global.Roles)));
public ObservableCollection<string> Pos { get => _pos; }
public ObservableCollection<string> Role { get => _role; }
public string RoleStr
{
get => _roleStr;
set => SetProperty(ref _roleStr, value);
}
public string PosStr
{
get => _posStr;
set => SetProperty(ref _posStr, value);
}
}
What I want to happen is when a Role is selected, based on that selection, only certain Positions should be shown. 例如,如果我选择“客户服务”作为角色,那么职位应该只包含“经理”、“CSS”和“无”。如果 Role 是“Admin”,那么 Position 应该只包含“None”,依此类推。
我的斗争是如何正确过滤这个。我看到了使用 CollectionViewSource 的一些东西,但我不确定如何让它与我的示例一起使用。
我有 5 个角色,每个角色都有不同的需要显示的职位列表。
使用 MINIMAL 额外代码或 XAML 进行这项工作的最佳方法是什么?
我真正不喜欢 WPF 的一件事是看似简单的事情需要大量代码才能使它们多次正常工作。
解决方案
首先,如果您认为 WPF 很复杂。所以,你用错了。
我建议你使用CollectionViewSource的过滤器作为流:
<ComboBox x:Name="empPositionCB" ItemsSource="{Binding MyPositionFilter}" SelectionChanged="RoleComboBox_SelectionChanged" ....../>
public ICollectionView MyPositionFilter { get; set; }
//ctor
public MyUserControlOrWindow()
{
//Before InitComponent()
this.MyPositionFilter = new CollectionViewSource { Source = MyPosObservableCollection }.View;
InitComponent();
}
public void RoleComboBox_SelectionChanged(object sender,EventArgs e)
{
//Get the selected Role (the ? is to prevent NullException (VS 2015 >))
Role r = empRoleCB.SelectedItem as Role;
//Apply the filter
this.MyPositionFilter.Filter = item =>
{
//Make you sure to convert correcteley your Enumeration, I used it here like a class
Position p = item as Position;
//Put your condition here. For example:
return r.ToLowers().Contains(p.ToLower());
//Or
return (r != null && r.Length >= p.Length);
};
}
过滤器不会更改您的集合,所有隐藏的项目都保留在您的 ObservableCollection 中。
推荐阅读
- python - 图像处理中mscn系数的直方图
- java - Flutter - VS Code Flutter 模拟器坏了
- node.js - 如何在 Nodejs 应用程序中使用 Dbeaver、Sequelize 和迁移处理 Postgres 数据库?
- swift - 在社交服务应用中分享内容时可以使用“CloudKit 的共享数据库”吗?
- javascript - 如何让模态在一段时间内从按钮获取值
- c# - VisualStudio 将我所有的代码高亮显示为绿色,我不知道如何禁用此效果/功能
- java - 没有从字符串值反序列化的字符串参数构造函数/工厂方法('http://localhost:8080/categories/1')
- javascript - 如何导入 npm 包
- mongodb - 为什么这个填充给我一个未找到的函数错误?
- reactjs - 如何在 React 的 JS 类中重定向到另一个路由?