Tuesday, 28 July 2009

Dynamic Data Custom Field Template – Values List, Take 2

An alternative way of doing the Dynamic Data Custom Field Template – Values List this version uses the UIHint’s ControlParameters property to pass in values to the control.

[MetadataType(typeof(Value.Metadata))]
partial class Value
{
    internal class Metadata
    {
        public object Id { get; set; }
        [UIHint("ValuesList", null, "ValueList", "Y,N,N/A")]
        //[ValuesList("Y,N,N/A")]
        public object TestR { get; set; }
        [UIHint("ValuesList", null, "ValueList", "Y,N,Other")]
        //[ValuesList("Y,N,Other")]
        public object Test { get; set; }
    }
}

Listing 1 – Metadata using the UIHint’s ControlParameters

See the example of using UIHint’s ControlParameters in Listing 1. In the above example you can see that I am passing in the ValueList in the UIHint’s ControlParameters as a key value pair.

/// <summary>
/// Populates a list control with all the values from a parent table.
/// </summary>
/// <param name="listControl">The list control to populate.</param>
protected new void PopulateListControl(ListControl listControl)
{
    var uiHint = Column.GetAttribute<UIHintAttribute>();
    if (uiHint == null || uiHint.ControlParameters.Count == 0 || 
        !uiHint.ControlParameters.Keys.Contains("ValueList"))
        throw new InvalidOperationException(String.Format(
            "ValuesList for FieldTemplate {0} field is missing from UIHint",
            Column.Name));

    var valuesList = ValuesListAttribute(
        uiHint.ControlParameters["ValueList"].ToString());
    if (valuesList.Count() == 0)
        throw new InvalidOperationException(String.Format(
            "ValuesList for FieldTemplate {0} field, is empty",
            Column.Name));

    listControl.Items.AddRange(valuesList);
}

Listing 2 – PopulateListControl

In Listing 2 you can see the extraction of the ValuesList from the UIHint’s ControlParameters collection.

So Listings 1 & 2 will get you the same as the previous article but without the new attribute.

Take 2

In take two of this control binh said “But would you change a little to handle to have combobox with value and display value. The Value will be save to database and The Display value will be showed to user.” so I thought I would add this version here.

My personal view is this should be done either via an FK relationship or a Enum value. (Both my Your First FieldTemplate and Dynamic Data Preview 4 have an Enum FieldTemplate) but here goes.

In the Edit FieldTemplate this is all you need to do is modify the ValuesList method.

public ListItem[] GetValuesList(String values)
{
    var items = values.Split(new char[] { ',', ';' });
    var listItems = (from item in items
                     select new ListItem()
                     {
                         Text = item.Split(new char[] { '|' })[1],
                         Value = item.Split(new char[] { '|' })[0]
                     }).ToArray();
    return listItems;
}
Listing 3 – updated ValuesListAttribute
[MetadataType(typeof(Value.Metadata))]
partial class Value
{
    internal class Metadata
    {
        public object Id { get; set; }
        [UIHint("ValuesList", null, "ValueList", "1|Y,2|N,3|N/A")]
        public object TestR { get; set; }
        [UIHint("ValuesList", null, "ValueList", "1|Y,2|N,3|Other")]
        public object Test { get; set; }
    }
}

Listing 4 – sample metadata

Here you can see that the values and text are seperated by the pipe symbol ‘|’. However having done this you would now need to create a ValuesList (ReadOnly) FieldTemplate to get the ValuesList and the match the value in the field and then display the correct value, which in my opinion would be quite messy, so here I will stick to using Enums.

Download

9 comments:

James said...

Steve, thanks for the great web site and the help with Dynamic Data.

You mentioned using Enums instead, but what if your table uses NCHAR(1) codes instead of INTs (e.g. L=Low,H=High). Can you still use Enum data types for this?

Stephen J. Naughton said...

Enums will not work with non int values but the above sample should.

Steve :D

custom research paper said...
This comment has been removed by a blog administrator.
Tali said...

is UIHint like ajax auto complete?

Stephen J. Naughton said...

No it is an Attribute applied to Partial classes to tell Dynamic Data which FieldTemplate to use over the default.

Steve :D

Unknown said...

hi Steve,

There's any elegant manner to get the values from database and load the ValuesList? I was checking Dynamic Data Extensions ValueList template and works with predefined values (like this example), but I need to replace some fields with DropDownList with data from other detail tables.

Thanks in advance, as usual.

Stephen J. Naughton said...

Hi Rodrigo, yes I do have a drop down list populated from the database and shows a sorted distinct list from the current column.

Steve

Unknown said...

hi Steve,

It works! :D but how I can show in the List.aspx's gridview the selected value that I chose in Insert or Edit form? I mean, the ValueList shows (in Insert and Edit mode) something like this:

1 - Apple
2 - Cherry
3 - Banana

but in List mode that column display the associated id (1, 2 or 3), not the description (Apple or so)

Thanks in advance

Stephen J. Naughton said...

Hi Rodrigo, the ValuesList ahould just show a list of values not pairs i.e. 1,Y,2,N,3,H just Y,N,H bit sure why you are getting that in List page, email me dorect and I will send you a working field template.