In a prior post, I blogged about creating a custom class inheriting from System.Web.Mvc.DataAnnotationsModelMetadataProvider to provide localized display names for my models.

I was disappointed to find that the MvcContrib grid doesn't use the metadata provider for column names - it just splits "Pascal-case" property names into words (e.g. "FromDate" to "From Date") if a name hasn't been explicitly assigned.

    public string DisplayName
    {
        get
        {
            if (this._doNotSplit)
            {
                return this._displayName;
            }
            return this.SplitPascalCase(this._displayName);
        }
    }

 

…so I had to use the "Named" method to assign my localized column names:

Html.Grid(Model.Items)
    .Attributes(@class => "mvcContribGrid jqStyleAlternateItems", border => "1")
    .HeaderRowAttributes(new Dictionary<string, object> { { "valign", "bottom" } })
    .RowStart(row => "<tr valign=\"top\">")
    .Sort(Model.MvcContribGridSortOptions)
    .Columns(column =>
    {
        column.For(x => x.BarCode)
         .Named(LocalizedResource.BarCode)
            .Action(x => Response.Write(string.Format(barCodeFormat, x.BarCode, x.Id)));
        column.For(x => x.Owner)
            .Named(LocalizedResource.Owner);
        column.For(x => x.Description)
            .Named(LocalizedResource.Description);
        column.For(x => x.RetentionCode)
            .Named(LocalizedResource.RetentionCode);
        column.For(x => x.StatusDescription)
            .Named(LocalizedResource.Status);
        column.For(x => x.LegalHold)
            .Named(LocalizedResource.LegalHold)
            .Action(x => Response.Write((x.LegalHold) ? checkMarkCell : emptyCell));
        column.For(x => x.TaxHold)
            .Named(LocalizedResource.TaxHold)
            .Action(x => Response.Write((x.TaxHold) ? checkMarkCell : emptyCell));
        column.For(x => x.FromDate)
            .Named(LocalizedResource.FromDate)
            .Format(dateFormat)
            .Attributes(data => dateColumnAttributes);
        column.For(x => x.ToDate)
            .Named(LocalizedResource.ToDate)
            .Format(dateFormat)
            .Attributes(data => dateColumnAttributes);
        column.For(x => x.EligibleRetirementDate)
            .Named(LocalizedResource.EligibleRetirementDate)
            .Format(dateFormat)
            .Attributes(data => dateColumnAttributes);
    }).Render();

 

That seemed like a lot of extra work though, since I'd already gone to the trouble of creating a custom model metadata provider, so I created an extension method for ColumnBuilder<T>:

   1:  public static class MvcContribGridColumnExtensionMethods
   2:  {
   3:      public static IGridColumn<T> WithAutonamedColumnFor<T>(
   4:          this ColumnBuilder<T> @this, 
   5:          Expression<Func<T, object>> propertySpecifier) where T : class 
   6:      {
   7:          var column = (GridColumn<T>) @this.For(propertySpecifier);
   8:   
   9:          ModelMetadata metadata = ModelMetadataProviders.Current
  10:              .GetMetadataForProperty(() => null, typeof(T), column.Name);
  11:   
  12:          return column.Named(metadata.DisplayName);
  13:      }
  14:  }

Line 7 uses the ColumnBuilder object's standard "For" method to initialize the column.

Line 9 gets the current model metadata provider for the model class and the current property (which for my site is my custom provider).

Line 12 returns the IGridColumn<T> object with the DisplayName assigned by the model metadata provider.

Now in my view I can get rid of the ".Named" calls and just use my ".WithAutomatedColumnFor" extension instead of the standard ".For" and ".Named" methods to initialize each column:

Html.Grid(Model.Items)
    .Attributes(@class => "mvcContribGrid jqStyleAlternateItems", border => "1")
    .HeaderRowAttributes(new Dictionary<string, object> { { "valign", "bottom" } })
    .RowStart(row => "<tr valign=\"top\">")
    .Sort(Model.MvcContribGridSortOptions)
    .Columns(column =>
    {
        column.WithAutonamedColumnFor(x => x.BarCode)
            .Action(x => Response.Write(string.Format(barCodeLinkFormat, x.BarCode, x.Id)));
        column.WithAutonamedColumnFor(x => x.Owner);
        column.WithAutonamedColumnFor(x => x.Description);
        column.WithAutonamedColumnFor(x => x.RetentionCode);
        column.WithAutonamedColumnFor(x => x.StatusDescription);
        column.WithAutonamedColumnFor(x => x.LegalHold)
            .Action(x => Response.Write((x.LegalHold) ? checkMarkCell : emptyCell));
        column.WithAutonamedColumnFor(x => x.TaxHold)
            .Action(x => Response.Write((x.TaxHold) ? checkMarkCell : emptyCell));
        column.WithAutonamedColumnFor(x => x.FromDate)
            .Format(dateFormat)
            .Attributes(data => dateColumnAttributes);
        column.WithAutonamedColumnFor(x => x.ToDate)
            .Format(dateFormat)
            .Attributes(data => dateColumnAttributes);
        column.WithAutonamedColumnFor(x => x.EligibleRetirementDate)
            .Format(dateFormat)
            .Attributes(data => dateColumnAttributes);
    }).Render();