Passing Arguments to a Dynamic Data Field Template from a UIHint Attribute
Update: Make sure to also check out: Generic Access to ASP.NET Dynamic Data UIHint Attribute Values
I’ve been working with Dynamic Data websites on and off for the last couple of weeks in order to prepare some screen casts I'm doing that demonstrate how to use the Infragistics toolset with Dynamic Data.
As I started building my sample I quickly found that I needed
to pass arguments from a UIHint attribute in my model’s meta-data up to a field
template.
The context I am working in features two auditing columns that are on each of my tables: CreatedOn and ModifiedOn.
The business rules are simple: when adding a record both fields must have the current date and time. When editing a record the ModifiedOn field must always have the current date and time – overwriting the existing data.
The field template I needed is easy to create, but it does require that I pass in an argument telling the template whether or not to overwrite the date or to simply add the data if nothing is there.
Here’s how I implemented my solution.
I updated the model with the following meta-data:
[MetadataType(typeof(Intervew_Metadata))]
public partial class Interview{}
public class Intervew_Metadata
{
[UIHint("DateTimeAutoFill")]
public object CreatedOn;
[UIHint("DateTimeAutoFill",null,"Overwrite","true")]
public object ModifiedOn;
}
My two date fields are decorated with the UIHint attribute signaling to Dynamic Data that the control used to render these fields is my custom DateTimeAutoFill templates. The ModifiedOn field is using a params list to pass in a series of name/value arguments.
Here is my field template markup:
<%@ Control Language="C#" CodeFile="DateTimeAutoFill_Edit.ascx.cs" Inherits="DateTime_EditField" >
<%@ Register Assembly="Infragistics35.WebUI.WebDateChooser.v8.1, Version=8.1.20081.1000, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb"
Namespace="Infragistics.WebUI.WebSchedule" TagPrefix="igsch" >
<igsch:WebDateChooser value="<%# FieldValueEditString %>" id="WebDateChooser1" runat="server">
</igsch:WebDateChooser>
<asp:RequiredFieldValidator runat="server" id="RequiredFieldValidator1" controltovalidate="WebDateChooser1" display="Dynamic" enabled="false"></asp:RequiredFieldValidator>
<asp:DynamicValidator runat="server" id="DynamicValidator1" controltovalidate="WebDateChooser1" display="Dynamic"></asp:DynamicValidator>
The ASCX is pretty basic. All that is here is my UI control and the needed validation controls.
Here’s the code-behind:
using System.ComponentModel.DataAnnotations;
...
protected override void OnPreRender(EventArgs e)
{
UIHintAttribute hint = null;
bool overwrite = false;
hint = (UIHintAttribute)this.Column.Attributes[typeof(UIHintAttribute)];
if (hint != null)
{
if (hint.ControlParameters.Count > 0)
{
if (hint.ControlParameters["Overwrite"] != null)
{
overwrite = Convert.ToBoolean(hint.ControlParameters["Overwrite"]);
}
}
}
if (overwrite)
{
this.WebDateChooser1.Value = DateTime.Now.ToString();
}
else
{
if (string.IsNullOrEmpty(this.WebDateChooser1.Value.ToString()))
{
this.WebDateChooser1.Value = DateTime.Now.ToString();
}
}
base.OnPreRender(e);
}
I chose to hook into the PreRender event so that I knew I was out of the way of any Dynamic Data processing and late enough in the page event lifecycle that all the data would be available.
The most interesting part about this code is how you get to the argument values. The values from the UIHint attribute are passed to the template in the Columns.Attribute collection. You can access the contents of the Attributes either via index or by passing in the type of the attribute that you are looking for.
Small Tangent
I can’t think of any reason why there would be more that one attribute of the same type so passing the type in seems like the best way to proceed – I could be totally wrong on this however.I resist passing in the index because since I don’t know how the index position are decided, I don’t feel comfortable passing in hard-coded index position values. When debugging this sample I noticed that the UIHint attributed showed up in the 4th index position which I thought was curious because the UIHint attribute was the only attribute I added to the meta-data.
Once the hint attribute is found the next step is to query the ControlParameters collection for the arguments passed to the template. In this case the only option you have is to request the name/value pair by the string you used to define the argument in the meta-data. The rest of the code simply formats the controls according to my business rules.
I know this isn't a picture-perfect implementation for these fields. Really they should be read-only at all times and not give the user a chance to edit the values, but like I said this is just me getting to know the system.
Hopefully you will find this useful as you are building out your own dynamic data field templates!
Update: Make sure to also check out: Generic Access to ASP.NET Dynamic Data UIHint Attribute Values