Paley
Paley

Reputation: 51

Data validation on a ListBox in WPF

I have a ListBox bound to an ObservableCollection of type T - each ListBoxItem is a checkbox with IsChecked bound to a bool property in T. I want to validate the checked items in the ListBox so that at least one checkbox must be ticked - if none of the check boxes are ticked I want to show a red border (standard validation notification) around the ListBox.

How do I go about doing that? Can I use ValidatesOnDataErrors?

Upvotes: 4

Views: 3200

Answers (2)

Patrick Stalph
Patrick Stalph

Reputation: 870

Your goal is to validate selected items of a ListBox: at least one selected item is required. First, there are different ways to handle the selection itself:

a) You can use the ListBox selection mechanism via ListBox.SelectedItem. I guess, you can specifiy the binding as SelectedItem="{Binding SelectedThing, ValidatesOnNotifyDataErrors=True}" and WPF's regular validation works. Not sure, if this works well with multi-selection.

b) You can use ListBox.SelectedItems. Binding is not possible and needs to be faked via code behind event handler. Thus, WPF's validation cannot trigger here.

c) You use your own IsSelected property (or similar) per item, either explicitely bound to your viewmodel via CheckBox or implicitely via ListBoxItem.IsSelected (via ListBox.ItemContainerStyle).

From here you could create a bool IsValidSelection property in your viewmodel that updates whenever the selection changed. Or you can run validation rules on any of the resulting properties of your viewmodel (e.g. SelectedItems). However, you don't validate the bound ListBox.ItemSource itself! Therefore WPF's standard mechanisms don't work (the list box doesn't get a red border or whatever).

Workarounds

You can explicitely create error notifications by showing an otherwise invisible Label and binding its visibility to the above-mentioned bool IsValidSelection property. This is a very explicit way, not using WPF validation at all.

You can modify your INotifyDataErrorInfo (or similar) implementation to trigger errors on a different property name. This is not possible, if you use a generic ValidatableViewModel<T> (like me). I guess this was the intention of the other answer.

Upvotes: 0

Robert Rossney
Robert Rossney

Reputation: 96920

Implement IDataErrorInfo in the class that exposes the ObservableCollection<T> property and make the indexer return an error for that property's name if all of the objects in the collection have a value of false in their boolean property. Then use the DataErrorValidationRule in your binding's ValidationRules.

Upvotes: 1

Related Questions