




















































Letting a user work with groups of related data is a requirement of almost every application. It includes displaying a group of people, editing product details, and so on. These groups of data are generally contained in forms and the Silverlight DataForm (from the Silverlight Toolkit) is just that—a form.
In the next few recipes, you'll learn how to work with this DataForm. As of now, let's start off with the basics, that is, displaying and editing the data.
For this recipe, we're starting with a blank solution, but you do need to install the Silverlight Toolkit as the assemblies containing the DataForm are offered through this. You can download and install it from http://www.codeplex.com/Silverlight/. You can find the completed solution in the Chapter05/Dataform_DisplayAndEdit_Completed folder in the code bundle that is available on the Packt website.
We're going to create a Person object, which will be displayed through a DataForm. To achieve this, we'll carry out the following steps:
<Grid x_Name="LayoutRoot"> <Grid.RowDefinitions> <RowDefinition Height="40" ></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <TextBlock Text="Working with the DataForm" Margin="10" FontSize="14" > </TextBlock> <df:DataForm x_Name="myDataForm" AutoEdit="False" CommandButtonsVisibility="All" Grid.Row="1" Width="400" Height="300" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top" > </df:DataForm> </Grid>
public class Person { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime DateOfBirth { get; set; } }
public Person person { get; set; } private void InitializePerson() { person = new Person() { ID = 1, FirstName = "Kevin", LastName = "Dockx", DateOfBirth = new DateTime(1981, 5, 5) }; }
InitializePerson(); myDataForm.CurrentItem = person;
To start off, we needed something to display in our DataForm: a Person entity. This is why we've created the Person class: it will be bound to the DataForm by setting the CurrentItem property to an object of type Person.
Doing this will make sure that the DataForm automatically generates the necessary fi elds. It looks at all the public properties of our Person object and generates the correct control depending on the type. A string will be displayed as a TextBox, a Boolean value will be displayed as a CheckBox, and so on.
As we have set the CommandButtonsVisibility property on the DataForm to All, we get an Edit icon in the command bar at the top of the DataForm. (Setting AutoEdit to False makes sure that we start in the display mode, rather than the edit mode). When you click on the Edit icon, the DataForm shows the person in the editable mode (using the EditItemTemplate) and an OK button appears. Clicking on the OK button will revert the form to the regular displaying mode. Do keep in mind that the changes you make to the person are persisted immediately in memory (in the case of a TextBox, when it loses focus).
If necessary, you can write extra code to persist the Person object from the memory to an underlying datastore by handling the ItemEditEnded event on the DataForm.
At this moment, we've got a DataForm displaying a single item that you can either view or edit. But what if you want to cancel your edit? As of now, the Cancel button appears to be disabled. As the changes you make in the DataForm are immediately persisted to the underlying object in the memory, cancelling the edit would require some extra business logic. Luckily, it's not hard to do.
First of all, you'll want to implement the IEditableObject interface on the Person class, which will make sure that cancelling is possible. As a result, the Cancel button will no longer be disabled. The following code is used to implement this:
public class Person : IEditableObject { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime DateOfBirth { get; set; } public void BeginEdit() {} public void CancelEdit() {} public void EndEdit() {} }
This interface exposes three methods: BeginEdit, CancelEdit, and EndEdit. If needed, you can write extra business logic in these methods, which is exactly what we need to do. For most applications, you might want to implement only CancelEdit, which would then refetch the person from the underlying data store. In our example, we're going to solve this problem by using a different approach. (You can use this approach if you haven't got an underlying database from which your data can be refetched, or if you don't want to access the database again.) In the BeginEdit method, we save the current property values of the person. When the edit has been cancelled, we put them back to the way they were before. This is shown in the following code:
public void BeginEdit() { // save current values tmpPerson = new Person() { ID = this.ID, FirstName = this.FirstName, LastName = this.LastName, DateOfBirth = this.DateOfBirth }; } public void CancelEdit() { // reset values ID = tmpPerson.ID; FirstName = tmpPerson.FirstName; LastName = tmpPerson.LastName; DateOfBirth = tmpPerson.DateOfBirth; }
Now, cancelling an edit is possible and it actually reverts to the previous property values.
The DataForm exposes various events such as BeginningEdit (when you begin to edit an item), EditEnding (occurs just before an item is saved), and EditEnded (occurs after an item has been saved). It also exposes properties that you can use to defi ne how the DataForm behaves.
As you might have noticed, the DataForm includes validation on your fields automatically. For example, try inputting a string value into the ID field. You'll see that an error message appears. This is beyond the scope of this recipe, but more on this will be discussed in the Validating the DataForm recipe.
There are different levels of managing the editing of an object. You can manage this on the control level itself by handling events such as BeginningEdit or ItemEditEnded in the DataForm. Besides that, you can also handle editing on a business level by implementing the IEditableObject interface and providing custom code for the BeginEdit, CancelEdit, or EndEdit methods in the class itself. Depending on the requirements of your application, you can use either of the levels or even both together.
In this recipe, we've seen how the DataForm is created automatically. For most applications, you require more control over how your fi elds, for example, are displayed. The DataForm is highly customizable, both on a template level (through template customization) and on how the data is generated (through data annotations). If you want to learn about using the DataForm to display or edit a list of items rather than just one, have a look at the next recipe, Displaying and editing a collection using the DataForm.
In the previous recipe, you learned how to work with the basic features of the DataForm. You can now visualize and edit an entity. But in most applications, this isn't enough. Often, you'll want to have an application that shows you a list of items with the ability to add a new item or delete an item from the list. You'll want the application to allow you to edit every item and provide an easy way of navigating between them. A good example of this would be an application that allows you to manage a list of employees.
The DataForm can do all of this and most of it is built-in. In this recipe, you'll learn how to achieve this.
For this recipe, we're starting with the basic setup that we completed in the previous recipe. If you didn't complete that recipe, you can find a starter solution in the Chapter05/ Dataform_Collection_Starter folder in the code bundle that is available on the Packt website. The finished solution for this recipe can be found in the Chapter05/Dataform_ Collection_Completed folder.
In any case, you'll need to install the Silverlight Toolkit as the assemblies containing the DataForm are offered through it. You can download and install it from http://www.codeplex.com/Silverlight/.