Our What's New in v24.2 webpage includes product-specific surveys. Your response to our survey questions will help us measure product satisfaction for features released in this major update and help us refine our plans for our next major release.
When defining a Validation Rule, you can use it to validate a collection property. This topic describes collection validation specifics. For general information on the contextual validation concept, refer to the Validation Rules topic.
Built-in validation rules can be applied to a collection property involved in a relationship (marked with the Association attribute). In this instance, a validation rule is evaluated for all the collection elements rather than for the master object, ensuring that each collection element is valid. So, when specifying parameters of a rule applied to a collection property, you need to specify them in the context of a collection element. For instance, the rule’s RuleBaseAttribute.TargetCriteria should not contain references to the master object’s properties and should only include properties of the collection element. Additionally, you will need to specify a collection element’s property that must be checked via the TargetPropertyName named parameter. In the following code snippet, RuleUniqueValue is applied to the Collection property, to ensure that all the collection elements’ StringProperty property values are unique:
When applied to collection properties, certain validation rules, such as the RuleRange and RuleValueComparison rules, can use aggregate functions. The attributes corresponding to these rules expose the TargetCollectionAggregate property that specifies the aggregate function. When a value is assigned to this property (by setting the corresponding named parameter or via the Application Model), the validation rule does not check the collection property’s elements. Instead, it checks the specified aggregate function. For example, the following code snippet illustrates the RuleValueComparison rule applied to the Collection property. In this example, the rule ensures that the sum of the collection elements’ IntegerProperty property values does not equal zero:
ImportsDevExpress.Data.Filtering'...
<DefaultClassOptions> _
PublicClass AggregateFunction
Inherits BaseObject
PublicSubNew(ByVal session As Session)
MyBase.New(session)
EndSub
<RuleValueComparison("RuleWithAggregateFunction", _
DefaultContexts.Save, ValueComparisonType.NotEquals, 0, _
TargetPropertyName:=NameOf(AggregateFunctionCollectionElement.IntegerProperty), _
TargetCollectionAggregate:=Aggregate.Sum), _
Association("AggregateFunction-AggregateFunctionCollectionElements"), _
Aggregated()> _
PublicReadOnlyProperty Collection() As XPCollection( _
Of AggregateFunctionCollectionElement)
GetReturn GetCollection( _
Of AggregateFunctionCollectionElement)(NameOf(Collection))
EndGetEndPropertyEndClassPublicClass AggregateFunctionCollectionElement
Inherits BaseObject
Private owner_Renamed As AggregateFunction
Private integerProperty_Renamed AsIntegerPublicSubNew(ByVal session As Session)
MyBase.New(session)
EndSubPublicProperty IntegerProperty() AsIntegerGetReturn integerProperty_Renamed
EndGetSet(ByVal value AsInteger)
integerProperty_Renamed = value
EndSetEndProperty
<Association("AggregateFunction-AggregateFunctionCollectionElements")> _
PublicProperty Owner() As AggregateFunction
GetReturn owner_Renamed
EndGetSet(ByVal value As AggregateFunction)
owner_Renamed = value
EndSetEndPropertyEndClass
If the RuleBaseAttribute.TargetCriteria property has been specified, then the demonstrated rule would calculate the sum over the suitable elements only.
The following aggregate functions are available:
Aggregate Function
Description
Avg
Evaluates the average of the collection elements’ property values. Requires the TargetPropertyName to be specified.
Count
Evaluates the number of elements contained in the collection. Does not require the TargetPropertyName to be specified.
Exists
Evaluates whether a collection element exists, which has a valid TargetPropertyName property’s value (the validity is defined by the actual validation rule).
Max
Evaluates the maximum of the collection elements’ property values. Requires the TargetPropertyName to be specified.
Min
Evaluates the minimum of the collection elements’ property values. Requires the TargetPropertyName to be specified.
Sum
Evaluates the sum of the collection elements’ property values. Requires the TargetPropertyName to be specified.
Note
RuleValueComparison is not checked if the collection property is empty. Use the RuleRequiredFieldAttribute instead.
#Aggregate Function Values in Custom Message Templates
When customizing validation message templates, you can include the aggregate function value in the template. For this purpose, use the {AggregatedTargetValue} parameter. The following code snippet illustrates this:
usingDevExpress.Data.Filtering;
usingSystem.Collections.ObjectModel;
//...
[DefaultClassOptions]
publicclassMessageTemplate : BaseObject {
[RuleRange("RuleWithCustomMessageTemplate", DefaultContexts.Save, 0, 50,
TargetPropertyName = nameof(MessageTemplateCollectionElement.DecimalProperty), TargetCollectionAggregate = Aggregate.Sum,
CustomMessageTemplate = "The sum of the {TargetPropertyName} values must be " +
"within {MinimumValue} and {MaximumValue} range. The current value is" +
" {AggregatedTargetValue}")]
publicvirtualIList<MessageTemplateCollectionElement> Collection { get; set; } = new ObservableCollection<MessageTemplateCollectionElement>();
}
publicclassMessageTemplateCollectionElement : BaseObject {
publicvirtualdecimal DecimalProperty { get; set; }
publicvirtual MessageTemplate Owner { get; set; }
}
// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
usingDevExpress.Data.Filtering;
//...
[DefaultClassOptions]
publicclassMessageTemplate : BaseObject {
publicMessageTemplate(Session session) : base(session) { }
[RuleRange("RuleWithCustomMessageTemplate", DefaultContexts.Save, 0, 50,
TargetPropertyName = nameof(MessageTemplateCollectionElement.DecimalProperty), TargetCollectionAggregate = Aggregate.Sum,
CustomMessageTemplate = "The sum of the {TargetPropertyName} values must be " +
"within {MinimumValue} and {MaximumValue} range. The current value is" +
" {AggregatedTargetValue}")]
[Association("MessageTemplate-MessageTemplateCollectionElements"), Aggregated]
public XPCollection<MessageTemplateCollectionElement> Collection {
get { return GetCollection<MessageTemplateCollectionElement>(nameof(Collection)); }
}
}
publicclassMessageTemplateCollectionElement : BaseObject {
privatedecimal decimalProperty;
private MessageTemplate owner;
publicMessageTemplateCollectionElement(Session session) : base(session) { }
publicdecimal DecimalProperty {
get { return decimalProperty; }
set { decimalProperty = value; }
}
[Association("MessageTemplate-MessageTemplateCollectionElements")]
public MessageTemplate Owner {
get { return owner; }
set { SetPropertyValue(nameof(Owner), ref owner, value); }
}
}
ImportsDevExpress.Data.Filtering'...
<DefaultClassOptions> _
PublicClass MessageTemplate
Inherits BaseObject
PublicSubNew(ByVal session As Session)
MyBase.New(session)
EndSub
<RuleRange("RuleWithCustomMessageTemplate", DefaultContexts.Save, _
0, 50, TargetPropertyName:=NameOf(MessageTemplateCollectionElement.DecimalProperty), _
TargetCollectionAggregate:=Aggregate.Sum, _
CustomMessageTemplate:= _
"The sum of the {TargetPropertyName} values must be " & _
"within {MinimumValue} and {MaximumValue} range. The current value is" & _
" {AggregatedTargetValue}"), _
Association("MessageTemplate-MessageTemplateCollectionElements"), Aggregated()> _
PublicReadOnlyProperty Collection() As XPCollection( _
Of MessageTemplateCollectionElement)
GetReturn GetCollection( _
Of MessageTemplateCollectionElement)(NameOf(Collection))
EndGetEndPropertyEndClassPublicClass MessageTemplateCollectionElement
Inherits BaseObject
Private decimalProperty_Renamed AsDecimalPrivate owner_Renamed As MessageTemplate
PublicSubNew(ByVal session As Session)
MyBase.New(session)
EndSubPublicProperty DecimalProperty() AsDecimalGetReturn decimalProperty_Renamed
EndGetSet(ByVal value AsDecimal)
decimalProperty_Renamed = value
EndSetEndProperty
<Association("MessageTemplate-MessageTemplateCollectionElements")> _
PublicProperty Owner() As MessageTemplate
GetReturn owner_Renamed
EndGetSet(ByVal value As MessageTemplate)
SetPropertyValue(NameOf(Owner), owner_Renamed, value)
EndSetEndPropertyEndClass
If you have any questions, submit a ticket to our Support Center.
No
Your feedback is appreciated.
By clicking “Accept All Cookies”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts.
Privacy Preference Center
When you visit a Developer Express Inc (“DevExpress”) website, it may store or retrieve information on your browser, mostly in the form of cookies. This information might be about you, your preferences or your device and is mostly used to make the site work as you expect it to. While the information does not usually directly identify you, it can give you a more personalized web experience. Because DevExpress respects your right to privacy, you can choose to disallow/disable the use of certain cookies. Click on different category headings to learn more and change our default settings. Keep in mind that blocking some types of cookies may impact your experience on the site and may affect the services DevExpress is able to offer to you. You cannot opt-out of our use of strictly necessary cookies as they are used to ensure the proper functioning of our Websites (such as remembering your settings, allowing you to log into your account, and other similar purposes). You may, however, opt-out of receiving and our use of non-essential cookies (including preference, functional, and targeting cookies) by changing your settings for each category listed below.
[Videos]
Our use of cookies may also collect information about what videos you have watched on our websites. You may opt-out of these cookies by changing your settings for functional and advertising cookies. We will ask you to review and update your choices at least once every two (2) years. By continuing to allow us to use these cookies you explicitly consent to our use of cookies and our disclosure of what videos you have watched on our Websites to our video hosting providers, such as YouTube, for a period of up to two (2) years.
Manage Consent Preferences
Strictly Necessary Cookies
Always Active
These cookies are necessary for the website to function properly and cannot be disabled. They are usually set in response to actions initiated by you – actions that amount to a request for services, such as setting your privacy preferences, logging onto the website, or populating website forms. You can set your browser to block or alert you about these cookies, but certain portions of the site will not work properly when these cookies are disabled. These cookies do not store any personally identifiable information.
Performance Cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand page popularity and determine how visitors move around the site. All information collected by these cookies are aggregated and therefore anonymous. If you disallow/disable these cookies, we will not know when you have visited our site and we will not be able to monitor its performance.
Functional Cookies
These cookies allow the website to provide enhanced functionality and personalization. They may be set by us or by third party providers whose services we have added to our pages. If you disallow/disable these cookies, some or all of these services may fail to function properly.
Targeting Cookies
These cookies may be set through our site by our advertising partners. They may be used by advertising partners to build a profile of your interests and display relevant advertisements on other sites. While these cookies do not store personal information, they do identify your browser and internet device. If you disallow/disable these cookies, you will experience less targeted advertising.