WPF 不提供此功能,但可以使用一些自定义编码来实现。
我创建了 3 个 ViewModel 类:
PreferencesVM - 这将是我们的 DataContext。它包含可以出现在 ComboBoxes 中的选项的主列表,还包含一个 SelectedOptions 属性,该属性跟踪在各种 ComboBoxes 中选择了哪些项目。它还有一个 Preferences 属性,我们会将 ItemsControl.ItemsSource 绑定到该属性。
PreferenceVM - 这代表一个 ComboBox。它有一个 SelectedOption 属性,ComboBox.SelectedItem 绑定到该属性。它还具有对 PreferencesVM 的引用和一个名为 Options 的属性(ComboBox.ItemsSource 绑定到此),该属性通过过滤器返回 PreferencesVM 上的选项,该过滤器检查项目是否可以显示在 ComboBox 中。
OptionVM - 表示 ComboBox 中的一行。
以下几点构成了解决方案的关键:
- 设置 PreferenceVM.SelectedOption 时(即选择了 ComboBoxItem),该项目将添加到 PreferencesVM.AllOptions 集合中。
- PreferenceVM 处理 Preferences.SelectedItems.CollectionChanged,并通过提升 Options 属性的 PropertyChanged 来触发刷新。
- PreferenceVM.Options 使用过滤器来决定要返回哪些项目 - 它只允许不在 PreferencesVM.SelectedOptions 中的项目,除非它们是 SelectedOption。
我上面描述的内容可能足以让您继续前进,但为了避免您头疼,我将在下面发布我的代码。
PreferencesVM.cs:
public class PreferencesVM
{
public PreferencesVM()
{
PreferenceVM pref1 = new PreferenceVM(this);
PreferenceVM pref2 = new PreferenceVM(this);
PreferenceVM pref3 = new PreferenceVM(this);
this._preferences.Add(pref1);
this._preferences.Add(pref2);
this._preferences.Add(pref3);
//Only three ComboBoxes, but you can add more here.
OptionVM optRed = new OptionVM("Red");
OptionVM optGreen = new OptionVM("Green");
OptionVM optBlue = new OptionVM("Blue");
_allOptions.Add(optRed);
_allOptions.Add(optGreen);
_allOptions.Add(optBlue);
}
private ObservableCollection<OptionVM> _selectedOptions =new ObservableCollection<OptionVM>();
public ObservableCollection<OptionVM> SelectedOptions
{
get { return _selectedOptions; }
}
private ObservableCollection<OptionVM> _allOptions = new ObservableCollection<OptionVM>();
public ObservableCollection<OptionVM> AllOptions
{
get { return _allOptions; }
}
private ObservableCollection<PreferenceVM> _preferences = new ObservableCollection<PreferenceVM>();
public ObservableCollection<PreferenceVM> Preferences
{
get { return _preferences; }
}
}
PreferenceVM.cs:
public class PreferenceVM:INotifyPropertyChanged
{
private PreferencesVM _preferencesVM;
public PreferenceVM(PreferencesVM preferencesVM)
{
_preferencesVM = preferencesVM;
_preferencesVM.SelectedOptions.CollectionChanged += new NotifyCollectionChangedEventHandler(SelectedOptions_CollectionChanged);
}
void SelectedOptions_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this,new PropertyChangedEventArgs("Options"));
}
private OptionVM _selectedOption;
public OptionVM SelectedOption
{
get { return _selectedOption; }
set
{
if (value == _selectedOption)
return;
if (_selectedOption != null)
_preferencesVM.SelectedOptions.Remove(_selectedOption);
_selectedOption = value;
if (_selectedOption != null)
_preferencesVM.SelectedOptions.Add(_selectedOption);
}
}
private ObservableCollection<OptionVM> _options = new ObservableCollection<OptionVM>();
public IEnumerable<OptionVM> Options
{
get { return _preferencesVM.AllOptions.Where(x=>Filter(x)); }
}
private bool Filter(OptionVM optVM)
{
if(optVM==_selectedOption)
return true;
if(_preferencesVM.SelectedOptions.Contains(optVM))
return false;
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
}
OptionVM.cs:
public class OptionVM
{
private string _name;
public string Name
{
get { return _name; }
}
public OptionVM(string name)
{
_name = name;
}
}
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new PreferencesVM();
}
}
MainWindow.xaml:
<Window x:Class="WpfApplication64.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ItemsControl ItemsSource="{Binding Path=Preferences}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=Options}" DisplayMemberPath="Name" SelectedItem="{Binding Path=SelectedOption}"></ComboBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
**请注意,为了减少代码行数,我提供的解决方案仅生成 3 个 ComboBoxes(不是 10 个)。