DataForm Control in Silverlight 3 and Customization


In this post, we will learn how to use the default data form control in Silverlight 3 and how to customize it.

Default Behavior:

At first we will create a Person class with the following properties:

public string firstName { get; set; }
public string lastName { get; set; }
public string companyName { get; set; }
public string designation { get; set; }
public DateTime joiningDate { get; set; }

Create a method which will return a List of Person object. For my example, my list will contain only 4 person objects.

Now place one data form control in the layout root. I am not caring about how it is placed or looks, my moto is to describe how to use it.  Name it "myDataForm". Then in the MainPage load event set the item source to:

myDataForm.ItemsSource = new Person().getEmployeeDetails();

Now run the project. You will see the default data form running with a tool bar on top which helps you to nevigate next, previous, first record, last record and also provides to button to add and delete data.For editing the existing data you can simple select any text and edit it. It will save automatically because by default the AutoCommit property is set to true.

Now let's have a look to all the events and properies that Microsoft provied for the DataForm :

Events

  • AddingItem - occurs just before an item is added to the collection
  • DeletingItem - occurs just before an item is deleted
  • BeginningEdit - occurs when you begin to edit an item
  • ItemEditEnding - occurs just before an item (which is being edited) is saved
  • ItemEditEnded - occurs just after an item (which has been edited) is saved
  • CurrentItemChanged - occurs when you change the selected item (like SelectionChanged in a ListBox control)
  • ValidatingItem - occurs when we are validating an item

Properties

  • AutoCommit - indicates whether to save the changes if the user presses the next (or the previous) button without pressing the Save button
  • AutoEdit - indicates whether to go into Edit mode automatically when you select a record
  • CancelButtonContent - lets the user set a content for the Cancel button
  • CommitButtonContent - lets the user set the content for the Commit button
  • CanUserAddItems - determines whether the user can add new items or not
  • CanUserDeleteItems - determines whether the user can delete an existing item or not
  • DescriptionViewerPosition - sets the position of description (each field may have a description, but we will see this in the following part of these series of posts)
    • Auto
    • BesideContent
    • BesideLabel
  • FieldLabelPosition - sets the position of labels for fields
    • Auto - automatically chooses the best position
    • Left - default, places the labels on the left side of the fields
    • Top - places the labels over the fields
  • Header - sets the header of the form
  • AutoGenerateFields - indicates whether fields should be automatically generated or not.

Now let's edit some properties:

<dataFormToolkit:DataForm x:Name="myDataForm" HorizontalAlignment="Center" VerticalAlignment="Center" AutoCommit="False" AutoEdit="False"  Header="Employee Details" ></dataFormToolkit:DataForm>

When you are editing an item, you cannot navigate through other items, because AutoCommit is set to false. If AutoEdit is set to true, you will immediately go in edit mode when you "open" an item. Now, we gave a name to our data form also by setting the header.

Fixing the Field Name:

I hope you have noticed that in the data form the field names are coming exactly as the property names of the Person class.

To fix this, you need to include System.ComponentModel.DataAnnotations into the project. Also include the namespace to Person class. Now before every property defination you need to add the [Display] property. For example:

[Display(Name="First Name",Description="Please enter your first name")]
public string firstName { get; set; }
 
[Display(Name = "Last Name", Description = "Please enter your Last name")]
public string lastName { get; set; }

[Display(Name = "Company", Description = "Please enter your company name")]
public string companyName { get; set; }

[Display(Name = "Designation", Description = "Please enter your designation details")]
public string designation { get; set; }
 
[Display(Name = "Joining Date", Description = "Select from the calander")]
public DateTime joiningDate { get; set; }

Now run the project.

Customized field:

Suppose you want to have a customized Hyperlink row. Then first you want to make the AutoGeneratedColumn field to false and then bind the properties to the data field. For example, your data form declaration should be like this:

<dataFormToolkit:DataForm x:Name="myDataForm" AutoGenerateFields="False" HorizontalAlignment="Center"  VerticalAlignment="Center" AutoCommit="False" AutoEdit="False"  Header="Employee Details" >
    <dataFormToolkit:DataForm.EditTemplate>
         <DataTemplate>
             <StackPanel>
                 <dataFormToolkit:DataField>
                         <TextBox Text="{Binding firstName}"/>
                 </dataFormToolkit:DataField>
                 <dataFormToolkit:DataField>
                         <TextBox Text="{Binding lastName}"/>
                 </dataFormToolkit:DataField>
                 <dataFormToolkit:DataField>
                         <TextBox Text="{Binding companyName}"/>
                 </dataFormToolkit:DataField>
                 <dataFormToolkit:DataField>
                         <TextBox Text="{Binding designation}"/>
                 </dataFormToolkit:DataField>
                 <dataFormToolkit:DataField>
                         <TextBox Text="{Binding joiningDate}"  />
                 </dataFormToolkit:DataField>
           </StackPanel>
        </DataTemplate>
     </dataFormToolkit:DataForm.EditTemplate>
 </dataFormToolkit:DataForm>

So if you want to have a hyperlink column you can specify like this:

<dataFormToolkit:DataField>
     <HyperlinkButton Content="Click here" NavigateUri="{Binding specificProperty}"/>
 </dataFormToolkit:DataField>

Data Validation:

With the following attributes you can mark your properties in order to apply a specific validation to them, when used in a DataForm control. All of them support ErrorMessage property, which you can use to assign a message, which will be shown if the input value is not valid. All these attributes are part of System.ComponentModel.DataAnnotations namespace. Here is a list of some of them:

<!--[if !supportLists]-->         <!--[endif]-->Required - use this attribute when you want to mark a property as required. If user does not enter a value, an error message will be shown.
Example: [Required]

<!--[if !supportLists]-->        <!--[endif]-->Range - use this attribute to specify a range for a property. The type of the property is not necessary to be a numeric one. This attribute will work with each property, if its type implements the IComparable interface.
Example: [Range(1, 500)]

<!--[if !supportLists]-->        <!--[endif]-->StringLength - use this attribute to restrict the length of a property.
Example: [StringLength(10)]

<!--[if !supportLists]-->         <!--[endif]-->RegularExpression - very powerful attribute. You can specify a regular expression to validate your property.
Example: [RegularExpression("[1-9][0-9]{3}")]

<!--[if !supportLists]-->        <!--[endif]-->EnumDataType - checks if the input is a valid item of a specific enumeration
Example: [EnumDataType(typeof(Genres))]

<!--[if !supportLists]-->         <!--[endif]-->CustomValidation - very powerful attribute, again. It gives you the freedom to define your own validation logic. You have to create a simple class and add a static method to it. The method return type should be boolean and this method has to accept one parameter with the same type of the property.
Example: CustomValidation(typeof(ClassName), "MethodName")]

For example:

[Display(Name="First Name",Description="Please enter your first name")]

[Required(ErrorMessage="Please enter the first name")]

For custom validation you can create one class like :

Class MyValidatorClass
{
  
  public static bool ValidateDate(DateTime myDate)
        {
            return (myDate < DateTime.Now);
        }
}

To apply these validations simply write:

[CustomValidation(typeof(MyValidaorClass),"ValidateDate")]
public DateTime joiningDate { get; set; }

Another great way to do data validation is in a property setter method. You apply your business logic there and if there is problem, just throw an exception. The DataForm control with catch this exception, when user tries to save the record. Here is an example:

public string MyProperty
        {
            get { return MyProperty; }
            set
            {
                if (String.IsNullOrEmpty(value))
                    throw ArgumentException("Provide Value");
                MyProperty = value;
            }
        }

You can define your own custom exception class and throw your own error message.

Please try this example and for any problem get back to me @ [email protected].

Cheers!!

Up Next
    Ebook Download
    View all
    Learn
    View all