09 March 2011

ASP.NET Dynamic Data - Default sort Table by specific column(s)

Hello,

      ASP.NET Dynamic Data brings major usability and RAD development changes to the existing ASP.NET data controls. RAD development is significantly increased by the use of a rich scaffolding framework.

      The DetailsView and GridView controls have been extended to display fields by using templates instead of by using hard-coded rules that are programmed in the controls. These templates are part of the project, and you can customize them to change their appearance or to specify which controls they use for rendering. This makes it very easy to make a change in one place in your site that specifies how to present dates for editing, as one example.

      But it is not so flexible as we wanted and it does not allow default sorting on tables.

      Here is a solution of how to make your ASP.NET dynamic data GridView sorted by default. This solution will require you to create an attribute - MySortByAttribute which will contain 2 proprieties: SortExpression (of type: String) and SortDirection (of type: SortDirection).



Here is the attribute code:
Code:
using System;
using System.Web.UI.WebControls;

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public sealed class MySortByAttribute: Attribute
{
    public MySortByAttribute()
    {
        SortExpression = string.Empty;
        SortDirection = SortDirection.Ascending;
    }

    public string SortExpression { get; set; }

    public SortDirection SortDirection { get; set; }
}

      SortExpression - if null or empty, then the column where MySortByAttribute is put will be used to sort the GridView. Else if not empty then will contain the column or columns to sort by, it will also allow to sort by ForeignKey Columns. Example of SortExpressions: "person.surname & person.person_city.desc_"
      SortDirection - will indicate how to sort - ascending or descending.

Here is the code that you need to put for a MetaForeignColumn in the DataModel:

Code:
[MySortByAttribute(SortExpression = "person.surname & person.person_city.desc_")]
public object person { get; set; }

 is the code which will sort the grid which is passed as a parameter.

Code:
protected void SortGrid(GridView gridView)
{
    foreach (MetaColumn column in Table.Columns)
    {
        var sortByAttr = column.Attributes.OfType<MySortByAttribute>.FirstOrDefault();
        if (sortByAttr != null)
        {
            var metaColumn = column as MetaForeignKeyColumn;
            string sortColumName = string.IsNullOrEmpty(sortByAttr.SortExpression) ? (metaColumn != null ? metaColumn.SortExpression : column.Name) : sortByAttr.SortExpression;
            gridView.Sort(sortColumName, sortByAttr.SortDirection);
            break;
        }
    }
}

      In this code Table is the MetaTable for which the page is displayed for.
      First I loop through each column and check if it contains the attribute: MySortByAttribute. If it contains it then create the SortExpression for the GridView.

There is nothing complicated here, so if you have any questions I will be glad to help.

4 comments:

andry said...

tutorial very good and hopefully can help me in building
something
thanks

MKing said...

First and foremost, thanks for posting this. With you help I was able to get this done.

For anyone trying to reproduce your example, there are a couple of inconsistencies that are worth noting.

1) In the MySortByAttribute class the SortDirection property is of type SortDirection. In the sample code for grid sorting, in the line that starts with gridView.Sort, you use it as though it is of type boolean (which doesn't compile). There's no need for the conditional operator here.

2) It might be worth noting that the capital-T Table in the SortGrid method foreach loop is the MetaTable that's being rendered (in my template code it was lowercase-t table which caused some head scratching.

3) The IEnumerable extension method OfType used in the SortGrid method needs a generic parameter with the type name, currently it takes it as a method parameter (which doesn't compile).

I posted an updated version of this method, which works with your attribute code here:
http://codepaste.net/bfnkaw

Roman Gherman said...

MKing,

Thanks for letting me know about my mistakes with the SortDirection and the generic parameter.

The thing is that I had 2 versions of the sorting and the old one was using boolean value, this is why that check was there.

What about the generic parameter - it was probably because of the text - to html converter :).


Now about the capital T from Table.

I have a protected property:
protected MetaTable Table { get; set; }

And on page init I give it the table of the datasource of the grid:

Table = GridDataSource.GetTable();

this is why it was a capital letter.

Thanks,
Roman

MKing said...

Nice, makes sense. Great way of getting this done, thanks for figuring it out and taking the time to share.

-Mike

Post a Comment

your thoughts are welcome:

Need more? Leave comments and subscribe to my blog.

.