Эта функциональность не предоставляется WPF, но ее можно реализовать с помощью некоторого пользовательского кодирования.
Я создал 3 класса ViewModel:
Предпочтения VM - Этобудет нашим DataContext.Он содержит основной список параметров, которые могут отображаться в комбинированных списках, а также содержит свойство SelectedOptions, которое отслеживает, какие элементы выбраны в различных комбинированных списках.Он также имеет свойство 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 и запускает обновление, вызывая PropertyChanged для свойства Options.
- 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 поля со списком (не 10).