Data Annotation Attributes - Building Layout from Business Object

  • 10 minutes to read

The Data Layout Control recognizes specific attributes from the System.ComponentModel.DataAnnotations namespace applied to a bound business object's properties. When building a layout, the Data Layout Control uses these attributes to give display names to layout items, specify the order of layout items, arrange items into groups and tabbed groups, specify the control's readonly status, assign masks to editors, etc.

NOTE
  • To use Data Annotation attributes, ensure that the System.ComponentModel.DataAnnotations assembly is added to your project.
  • If your data source is a custom object decorated with attributes and this object is not an IEnumerable collection, do not pass it to the control's DataLayoutControl.DataSource property directly. Instead, use the BindingSource component. Otherwise, data annotation attributes will not be parsed correctly.

Online Video

Consider the following MyClassTabsLayout business object, which contains multiple fields with no attributes applied. When this object is bound to a Data Layout Control, a linear layout is generated, as follows.

Code

Data Layout Control


public class MyClassTabsLayout {
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public DateTime BirthDate { get; set; }
    public GenderEnum Gender { get; set; }
    public string Group { get; set; }
    public DateTime HireDate { get; set; }
    public decimal Salary { get; set; }
    public string Title { get; set; }
    public enum GenderEnum { Male, Female }
}

DataLayoutControl-DataAnnotationAttributes-No.png

To combine items in groups, specify item order, assign custom captions, set masks for editors, etc., certain Data Annotation attributes can be applied to the object's fields. In the following code, Data Annotation attributes are applied to fields of the same business object. The Data Layout Control takes into account these attributes when generating a layout.

Code

Data Layout Control


using System.ComponentModel.DataAnnotations;

public class MyClassTabsLayout {
    // The two items below will be displayed by DataLayoutControl  
    // in a borderless Name group without a title
    [Display(GroupName = "<Name|>", Name = "Last name")]
    public string LastName { get; set; }
    [Display(GroupName = "<Name|>", Name = "First name", Order = 0)]
    public string FirstName { get; set; }
    //The four items below will go to a Contact tab within tabbed Tabs group. 
    [Display(GroupName = "{Tabs}/Contact", Order = 2), DataType(DataType.PhoneNumber)]
    public string Phone { get; set; }
    [Display(GroupName = "{Tabs}/Contact", Order = 4), DataType(DataType.EmailAddress)]
    public string Email { get; set; }
    //The two items below will go to the Address group within the Contact tab. 
    [Display(GroupName = "{Tabs}/Contact/Address", ShortName = "")]
    public string AddressLine1 { get; set; }
    [Display(GroupName = "{Tabs}/Contact/Address", ShortName = "")]
    public string AddressLine2 { get; set; }
    //The two items below will go to a horizontally oriented Personal group. 
    [Display(GroupName = "Personal-", Name = "Birth date")]
    public DateTime BirthDate { get; set; }
    [Display(GroupName = "Personal-", Order = 3)]
    public GenderEnum Gender { get; set; }
    //The four items below will go to the Job tab of the tabbed Tabs group 
    [Display(GroupName = "{Tabs}/Job", Order = 6)]
    public string Group { get; set; }
    [Display(GroupName = "{Tabs}/Job", Name = "Hire date")]
    public DateTime HireDate { get; set; }
    [Display(GroupName = "{Tabs}/Job"), DataType(DataType.Currency)]
    public decimal Salary { get; set; }
    [Display(GroupName = "{Tabs}/Job", Order = 7)]
    public string Title { get; set; }
    public enum GenderEnum { Male, Female }
}

DataLayoutControl-DataAnnotationAttributes-Yes.png

Layout Generation Attributes

The table below covers attributes that allow you to specify an item's visibility, label, hint, read-only state and display format. Certain attributes are used to position items in regular and tabbed groups.

Attribute

Attribute's Parameter

Description

System.ComponentModel.DataAnnotations.DisplayAttribute

GroupName

This parameter allows you to place a generated layout item into a group or tabbed group. If the parameter refers to a non-existing group, it will be automatically created.

Created Group Type

To specify the type of the created group, enclose the group name with the following characters.


[Display(GroupName = "[Name]")]
public string Notes { get; set; }

Group Item Orientation

You can specify the orientation of items within the created group by appending "|" and "-" characters to a group name. These specify the vertical and horizontal orientations of items respectively.

If the orientation is not specified using these characters, items are arranged vertically in this group. The orientation of items within the root group (the DataLayoutControl itself) is always vertical.


[Display(GroupName = "Personal-")]
public GenderEnum Gender { get; set; }
[Display(GroupName = "Personal-")]
public DateTime BirthDate { get; set; }

Nested Groups

To place a layout item into a group that is nested in another group, the GroupName parameter must specify the full path to the target group (including all parent groups). Group names should be delimited using the "/" character in the full path.


[Display(GroupName = "{Tabs}/Job")]
public string Title { get; set; }

Name

If specified, this parameter defines a label for the generated layout item. If the parameter is omitted, the layout item's label is specified by the property's name. You can set the parameter to an empty string to hide the layout item's label.


[Display(Name = "Last name")]
public string LastName { get; set; }

ShortName

The same as the Name parameter.

Description

Assigns a tooltip to the generated layout item.


[Display(Description = "Enter product amount")]
public int Quantity { get; set; }

Order

Specifies the order of the layout item among other layout items. If this attribute parameter is omitted, the layout item is pushed to the bottom of its parent group.


[Display(Order = 2)]
public GenderEnum Gender { get; set; }
[Display(Order = 1)]
public string Group { get; set; }

AutoGenerateField

Specifies whether or not a layout item (with a control) is automatically generated for the current field.


[Display(AutoGenerateField=false)]
public int ID{ get; set; }

System.ComponentModel.ReadOnlyAttribute

-

Specifies whether this generated editor is in read-only mode.


[ReadOnly(true)]
public double UnitPrice { get; set; }

System.ComponentModel.DataAnnotations.DisplayFormatAttribute

DataFormatString

Specifies the display format for the generated editor.

ApplyFormatInEditMode

Specifies whether the editor's display format must also apply in edit mode.


[DisplayFormat(DataFormatString = "p", ApplyFormatInEditMode = true)]
public object SalesVsTarget { get; set; }

Editor Type and Settings Attributes

The type of editors used to edit the bound object's properties can be specified using the System.ComponentModel.DataAnnotations.DataTypeAttribute, System.ComponentModel.DataAnnotations.EnumDataTypeAttribute and System.ComponentModel.DataAnnotations.MetadataTypeAttribute.

DataTypeAttribute

Attribute parameter

Created editor

DataType.Date

DateEdit


[DataType(DataType.Date)]
public object HireDate { get; set; }

DataType.DateTime

DateEdit

DataType.Duration

TimeSpanEdit

DataType.Time

TimeEdit

DataType.Text

TextEdit

DataType.MultilineText

MemoEdit

DataType.Password

TextEdit with password input enabled

(see RepositoryItemTextEdit.UseSystemPasswordChar).

DataType.Url

TextEdit

DataType.Currency

TextEdit with the numeric currency mask ("c").

DataType.Html

TextEdit

EnumDataTypeAttribute

Description

Allows you to replace numeric enumerator values with corresponding declarations.


[EnumDataType(typeof(ProductCategory))]
public int Category { get; set; }

public enum ProductCategory {
    Beverages = 1,
    Fruit = 2,
    Vegetables = 3,
    Meat = 4,
    Condiments = 5,
    Confections = 6,
    DairyProducts = 7,
    GrainsCereals = 8,
    Seafood = 9
}

MetadataTypeAttribute

Description

Allows you to derive data annotation attributes from another class.


[MetadataType(typeof(CompanyProductMetadata))]
public class Product {
    public double UnitPrice { get; set; }
}

public class CompanyProductMetadata {
    [ReadOnly(true)]
    public double UnitPrice { get; set; }
}

Validation Attributes

Attribute

Editor

System.ComponentModel.DataAnnotations.StringLengthAttribute

Specifies the maximum and minimum number of characters for string records within the editor.


[DataType(DataType.Password), StringLength(20, MinimumLength = 3)]
public string Password { get; set; }

System.ComponentModel.DataAnnotations.RangeAttribute

A numeric value should lie in a specific range, set by using this attribute.


[DataType(DataType.Currency), Range(200, 5000)]
public int Currency { get; set; }

System.ComponentModel.DataAnnotations.RequiredAttribute

Shows an error icon if an end-user is about to leave a modified editor when the edit value is null or an empty string.


[Required(AllowEmptyStrings=false)]
public string FirstName { get; set; }

System.ComponentModel.DataAnnotations.CompareAttribute

Compares the editor's value with another property. The entering of values that differ from the compared property's value is restricted.


[DataType(DataType.Password), Display(Name = "New Password")]
public string NewPassword { get; set; }

[DataType(DataType.Password), Compare("NewPassword",
     ErrorMessage="The new and confirmation passwords do not match"),
     Display(Name="Confirm Password")]
public string ConfirmPassword { get; set; }
See Also