Reputation: 682
I am looking for a way to prevent two (or more) ComboBoxes
from having the same SelectedItem
. I have multiple ComboBoxes
that all have the same ItemsSource
, each bound to a separate property in the view model.
<ComboBox Width="50" ItemsSource="{Binding Keys}" SelectedItem="{Binding LoadedBackgroundKey, NotifyOnValidationError=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<ComboBox Width="50" ItemsSource="{Binding Keys}" SelectedItem="{Binding LoadedForegroundKey, NotifyOnValidationError=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<ComboBox Width="50" ItemsSource="{Binding Keys}" SelectedItem="{Binding IncreaseSizeKey, NotifyOnValidationError=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
etc. In the ViewModel:
public Key LoadedBackgroundKey { get; set; }
public Key LoadedForegroundKey { get; set; }
public Key IncreaseSizeKey { get; set; }
private ObservableCollection<Key> _availableKeys;
public IEnumerable<Key> Keys => _availableKeys;
When the view model is loaded, _availableKeys
gets populated with the appropriate keys (A
, B
, etc.). I want to be able to prevent the selection of the same key in multiple comboboxes or (at the very least) give an error when the same key is selected in multiple boxes.
This question may be similar to what I am looking for, but I am not sure it quite works (maybe I just don't understand it properly). It also only accounts for the case of two ComboBoxes
. While I only displayed 3, I want this to be scalable over multiple Comboboxes
. Is a ValidationRule
the best approach? If so, how would I implement this, checking over all of the ComboBoxes
? Or is there an easier approach?
Upvotes: 0
Views: 89
Reputation: 169200
You could implement the INotifyDataErrorInfo
interface in your view model and perform your validation logic whenever any of the involved properties are set, e.g.:
public class ViewModel : INotifyDataErrorInfo
{
public Key LoadedBackgroundKey
{
get => keys[0];
set
{
Validate(nameof(LoadedBackgroundKey), value);
keys[0] = value;
}
}
public Key LoadedForegroundKey
{
get => keys[1];
set
{
Validate(nameof(LoadedForegroundKey), value);
keys[1] = value;
}
}
public Key IncreaseSizeKey
{
get => keys[2];
set
{
Validate(nameof(IncreaseSizeKey), value);
keys[2] = value;
}
}
public IEnumerable<Key> Keys { get; } = new ObservableCollection<Key> { ... };
private void Validate(string propertyName, Key value)
{
if (keys.Contains(value))
_validationErrors[propertyName] = "duplicate...";
else
_validationErrors.Remove(propertyName);
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
}
private readonly Key[] keys = new Key[3];
private readonly Dictionary<string, string> _validationErrors = new Dictionary<string, string>();
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public bool HasErrors => _validationErrors.Count > 0;
public IEnumerable GetErrors(string propertyName) =>
_validationErrors.TryGetValue(propertyName, out string error) ? new string[1] { error } : null;
}
Upvotes: 2