Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Required Enumeration Validation Attribute

0.00/5 (No votes)
5 Dec 2015 1  
This tip presents a ValidationAttribute that can be applied to enumeration properties. The normal RequiredValidationAttribute normally works but if numbers are assigned to the enumeration values, the default value is zero and that may not be valid.

Introduction

This is something that I created for another developer when he was having issues with validation. Normally, one does not have integer values assigned to enumerations, and when they are assigned, there is an enumeration that is assigned the value zero. The RequiredAttibute does not recognize that 0 may not be a valid enumeration, so does not flag it as an error. Normally, if you encounter this problem, enumerations would be used in a ComboBox, and this would only be a problem for a new record where a value has not yet been assigned to the ComboBox, so the default of “0” is used.

Solution

using System;
using System.ComponentModel.DataAnnotations;

    public class RequiredEnumAttribute : RequiredAttribute
    {
        public override bool IsValid(object value)
        {
            if (value == null) return false;
            var type = value.GetType();
            return type.IsEnum && Enum.IsDefined(type, value);;
        }
}

This is a very similar to the RequiredAttibute where the IsValid method is overridden. Initially, just check that the new value is not null, and then check if its value is an enumeration, and that the value is defined.

The Sample

The sample has a number of ComboBoxes that have their ItemsSource bound to a property that returns an enumeration of all the enumerations of a specific enumeration definition. The SelectedItem is bound to a separate property that is the type of the enumeration, or a Nullable of the enumeration. There are two properties for binding to the ItemsSource, one for an enumeration that does not have numeric assignments, and one that does. The one that has numeric assignments does not have an enumeration assigned to zero. As can be seen from the sample, the enumeration defaults to the integer value of zero even if a zero value is not assigned to the enumeration. A zero assignment will happen automatically if there are no assignment. Making an enumeration property Nullable will mean that there is no default value assigned to an enumeration, and the RequiredAttribute will force the user to select a value to continue. Manually assigning enumeration values and not assigning an enumeration for zero, and using the RequiredEnumAttribute can accomplish the same result.

If you investigate the XAML, you will see that the binding definition has a “ValidatesOnDataErrors=True” which is what tells the binding that it needs to check for errors using the IDataErrorInfo interface:

<ComboBox Grid.Row="4"
          Grid.Column="1"
          Margin="5"
          VerticalAlignment="Center"
          ItemsSource="{Binding TypeBs}"
          SelectedItem="{Binding TypeB3,
                                 ValidatesOnDataErrors=True}" />

I have often forgotten about needing this attribute, and I know that I have found this error when working with other developers.

The decoration for using this validation attribute is no different from any other validation attribute:

[RequiredEnum(ErrorMessage = "TypeB3 is required.")]
public TypeB TypeB3 { get; set; }

I have obviously significantly simplified the property since normally would raise the PropertyChanged event in a real application. All the arguments that can be used with the Required decoration can be used with the RequiredEnum because it is derived from the class.

Bonus

Because I have to implement IDataErrorInfo in the ViewModel to provide error validation, I have a class called ValidationViewModelBase class. It is used by the ViewModel to implement the interface required for the IDataErrorInfo. Since C# does not have multiple inheritance (which I think is a big mistake, and this is a good example of where multiple interface), if you use this class, you will probably want to include the INotifyPropertyChanged interface. However, you can easily adapt this code for your use, and thus easily provide the IDataErrorInfo interface code required when validation attributes are used.

History

  • 12/05/2015 Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here