ValidationRule To Enforce Unique Name
-
09-06-2019 - |
Question
I'm trying to write a custom WPF ValidationRule to enforce that a certain property is unique within the context of a given collection. For example: I am editing a collection of custom objects bound to a ListView and I need to ensure that the Name property of each object in the collection is unique. Does anyone know how to do this?
Solution
First, I'd create a simple DependencyObject class to hold your collection:
class YourCollectionType : DependencyObject {
[PROPERTY DEPENDENCY OF ObservableCollection<YourType> NAMED: BoundList]
}
Then, on your ValidationRule-derived class, create a property:
YourCollectionType ListToCheck { get; set; }
Then, in the XAML, do this:
<Binding.ValidationRules>
<YourValidationRule>
<YourValidationRule.ListToCheck>
<YourCollectionType BoundList="{Binding Path=TheCollectionYouWantToCheck}" />
</YourValidationRule.ListToCheck>
</YourValidationRule>
</Binding.ValidationRules>
Then in your validation, look at ListToCheck's BoundList property's collection for the item that you're validating against. If it's in there, obviously return a false validation result. If it's not, return true.
OTHER TIPS
I would only create a custom dependency object if there were other properties I wanted to bind to the rule. Since in this case all we're doing is attaching a single collection of values to check against, I made my <UniqueValueValidationRule.OtherValues>
property a <CollectionContainer>
.
From there, to get past the problem of the DataContext
not being inherited, <TextBox.Resources>
needed to have a <CollectionViewSource>
to hold the actual binding and give it a {StaticResource}
key, which OtherValues
could then use as binding source.
The validation rule itself then need only loop through OtherValues.Collection
and perform equality checks.
Observe:
<TextBox>
<TextBox.Resources>
<CollectionViewSource x:Key="otherNames" Source="{Binding OtherNames}"/>
</TextBox.Resources>
<TextBox.Text>
<Binding Path="Name">
<Binding.ValidationRules>
<t:UniqueValueValidationRule>
<t:UniqueValueValidationRule.OtherValues>
<CollectionContainer Collection="{Binding Source={StaticResource otherNames}}"/>
</t:UniqueValueValidationRule.OtherValues>
</t:UniqueValueValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>