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?

Was it helpful?

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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top