Create Quick Database Interfaces with ASP.NET Dynamic Data
Customizing using attributes
So far, you have briefly seen how ASP.NET Dynamic Data applications work. After you have seen how the different features of the application, you should next learn how you can control how data is displayed in the application.
Earlier, when looking at the Global.asax.cs
file, the ScaffoldAllTables
property was set to
true. This property value means that every table in the
model became active in the application for editing and
deleting. But maybe you would like to better control which
tables are active. To do this, you need to use
attributes. In the data model, the classes that represent
the tables are defined as partial classes. This means that
you can effectively continue adding features to these
classes, including specifying attributes. To write the
necessary code, you need to add a new file to your
project.
The easiest way to add this file is to right-click your project in Visual Studio's Solution Explorer and then choose the Add/Class command. Visual Studio will then ask you for a class name; choose any name you want, for instance "MetadataControl". Once the file has been created, you can start editing it.
Assuming for example, that you want to hide the employees table, you would add a partial class definition for the Employee class, originally defined in the ADO.NET entity model file NorthwindModel.Designer.cs (if you followed the naming convention suggested earlier). Replacing the skeleton public class definition written by Visual Studio, add the following code:
[ScaffoldTable(false)]
public partial class Employees
{
}
With this definition, the Employees class defined in the
original entity model gets extended, and the ScaffoldTable
attribute is added. This attribute is one of the key ones in
ASP.NET Dynamic Data. Many of the most important attributes
are defined in the System.ComponentModel.DataAnnotations
namespace. Other often-needed attributes include
ScaffoldColumn (of which you will soon see an example),
DisplayName, DisplayFormat, Range
and
UIHint
.
With the above ScaffoldTable attribute (and the value of false) in place, you should now run the application to see how it behaves. In the initial screen showing the names of tables in the data model, you should see that the Employees table link is missing. And, if you take a look for example at the Orders table, you can see that the hyperlinks to the table are also gone.
Notice how there are two ways to show and hide tables.
You can make all tables visible using the
ScaffoldAllTables
property in the
Global.asax.cs
file, and then hide them one by
one using attributes. The other option is to go the other
way around: leave ScaffoldAllTables
to false,
and then allow individual tables to become visible using the
ScaffoldTable
(true) attribute.
Next, let's see how you can control individual fields using attributes. Previously, you used partial classes to help in specifying the ScaffoldTable attribute, but if you wanted to have attributes associated with individual columns, you would need another kind of solution. Since you cannot have partial property definitions, you must use an additional class to define properties that are associated with database fields.
To do this, you start with a similar partial class like with the ScaffoldTable attribute, but you use the MetadataType attribute to associate another class with the original. Then, this additional class, called the metadata class, allows you to define public properties for each field in the data model which you want to control. The following example shows how this is done:
[MetadataType(typeof(EmployeesMetadata))]
public partial class Employees
{
}
class EmployeesMetadata
{
[DisplayName("Person's title")]
public object Title { get; set; }
}
Here, the partial class Employees is defined as before,
but also the MetadataType
attribute is applied
to the class. The constructor of this attribute accepts a
type as a parameter, which in turn points to the metadata
class called EmployeesMetadata
. This class is
then free to define new properties and associated field-
level attributes to them. For instance, here the
DisplayName
attribute (in the
System.ComponentModel
namespace) is associated
with the column Title to specify a new, more descriptive
title for the field. Of course, the property names must
match those in the database for this to work.
Modifying user interfaces
While understanding how attributes are applied in ASP.NET Dynamic Data applications is key to your success, you must also understand how you can customize the web page templates that together create the user interface for your application. As briefly mentioned before, ASP.NET Dynamic Data applications by default utilize an ASP.NET template file. This file is named Site.master, and can be found from the root folder of the project.If you wanted to change the user interface, then editing the Site.master file would be a good place to start. It utilizes XHTML code and defines a single content placeholder into which the actual pages are embedded at runtime. Furthermore, the master file uses CSS styles, which are in turn defined in the file Site.css. To do application-wide font and color changes, editing this style sheet file would give you a head start.
In addition to the template and style sheet files, you do of course have the actual .aspx pages that implement the four basic operations. This can be found inside the DynamicData\PageTemplates folder in your solution. For instance, you might wish to change how the listing pages operate. For this need, you would edit List.aspx.
Another option for customizations is the DynamicData\FieldTemplates folder. This folder contains the user controls that ASP.NET Dynamic Data uses to render different database field types. For instance, a Boolean field is shown as a checkbox to the user. If you wanted to change this, you could simply go and edit the files Boolean.ascx and Boolean_Edit.ascx. There usually are two controls defined for each data type: one for viewing and another for editing. Often, the viewer control is simply a read-only version of the edit control.
It is also possible to define your own user controls to work with your data. For instance, you might wish to change the control that is used to display dates. By default, the DateTime.ascx control uses a textbox control for this, but you could easily change this to, say, a calendar control. If you wanted to make this an application-wide change, then you could simply edit DateTime.ascx, and all date fields would change. You can also change the control on a field by field basis. This is done using attributes, just like with the previously shown ScaffoldTable and ScaffoldColumn attributes. Assume that you had implemented a calendar user control DataTimeCalendar.ascx like this:
<%@ Control Language="C#" AutoEventWireup="true"
CodeBehind="DateTimeCalendar.ascx.cs"
Inherits="DynamicDataTest.DynamicData.
FieldTemplates.DateTimeCalendar" %>
<asp:Calendar ID="Calendar1" runat="server">
</asp:Calendar>
This declaration mirrors any other user control
definition. However, for a user control to be suitable for
ASP.NET Dynamic Data use, you need to tweak the code-behind
file a bit. First, you need to change the inheritance
chain from the regular
System.Web.UI.UserControl
to
System.Web.DynamicData.FieldTemplateUserControl
.
Of course, you are not limited to controls that are available in ASP.NET. For instance if you have purchased a nice, feature-rich third-party control or created one on your own, you are free to use them in your ASP.NET Dynamic Data applications. Specifying which user control should be used when ASP.NET Dynamic Data renders the database views can be controlled using the UIHint attribute. This attribute is applied to metadata classes just like the ScaffoldColumn attribute. With the previous DateTimeCalendar user control declaration in place, you could use the UIHint attribute as follows:
[MetadataType(typeof(EmployeesMetadata))]
public partial class Employees
{
}
class EmployeesMetadata
{
...
[UIHint("DateTimeCalendar")]
public object HireDate { get; set; }
}
Here, the HireDate field of the Employees table is assigned the UIHint attribute with the value of "DateTimeCalendar". When ASP.NET Dynamic Data shows the table, the regular text label is replaced with the calendar control (Figure 7). Note that you also need to write a couple of lines of code to the user control's code behind file so that you can set the calendar to show the correct hire date:
protected override void OnDataBinding(EventArgs e)
{
base.OnDataBinding(e);
object val = FieldValue;
if (val != null)
{
Calendar1.SelectedDate = (DateTime)val;
Calendar1.VisibleDate = Calendar1.SelectedDate;
}
}
Click here for larger image
Figure 7. A custom calendar showing employee hire dates.
Other than this kind of code, it is quite easy to customize your pages with custom controls. As you can see, the row listings and editing pages need not solely rely on labels and text boxes.
Page 3 of 4
This article was originally published on June 8, 2009