2011-06-05 61 views
3

我在MVC中创建一个流畅的HtmlHelper - 创建一个基于HTML的网格。 我知道MVC的contrib和的WebGrid的 - 但我做我自己,并有一个具体的问题:MVC3基于剃刀的htmlhelper基于模型的lambda字段表达式

我进入这个:

@Html.DSGridFor().AddColumn(x=>x.FirstOrDefault().Message) 

,但我希望能够输入:

@Html.DSGridFor().AddColumn(x=>x.Message) 

当我以@ Html.DSGridFor()开始时调用的代码 - 接受基于页面的模型。

public static DSGridHelper<TModel> DSGridFor<TModel>(this HtmlHelper<TModel> html) 
{ 
    return new DSGridHelper<TModel>(html); 
} 

,然后在类DSGridHelper内我有这样的:

public DSGridHelper<TModel> AddColumn(Expression<Func<TModel, dynamic>> property, string HeaderText = null) 
     { 
      string ColumnName = (property.Body as MemberExpression).Member.Name; 

      DSGridColumn DSGC = new DSGridColumn(); 
      DSGC.ColumnName = ColumnName; 
      DSGC.HeaderText = HeaderText ?? ColumnName; 
      DSColumnList.Add(DSGC); 

      return this; 
     } 

public List<DSGridColumn> DSColumnList { get; set; } 

和此刻的列类是很基本的:

public class DSGridColumn 
    { 
     public DSGridColumn() 
     { 

     } 

     public string ColumnName { get; set; } 
     public string HeaderText { get; set; } 

    } 

我能得到这个代码工作正常使用基于字符串的列名称,但我希望剃刀页面中的声明代码在格式和强类型上都很简单。此刻我必须键入x => x.First()。但是我真的只需要x => x.Message来识别列。

我很感激任何帮助。

UPDATE

感谢贾斯汀我现在可以提供我/我们的代码。

查看:

@(Html.DSGridFor3().AddColumn(x => x.Message) 
        .AddColumn(x => x.Host) 
        .ToMvcString()) 

HTML辅助电话:

public static DSGridHelper3<T> DSGridFor3<T>(this HtmlHelper<IEnumerable<T>> htmlHelper) 
{ 
     return new DSGridHelper3<T>(htmlHelper); 
} 

返回类:

public class DSGridHelper3<T> 
    { 
     private HtmlHelper _htmlHelper; 
     //private IEnumerable<T> _dataList; 
     public List<DSGridColumn> DSColumnList { get; set; } 

     public DSGridHelper3(HtmlHelper<IEnumerable<T>> htmlHelper) 
     { 
      _htmlHelper = htmlHelper; 
      // _dataList = htmlHelper.ViewData.Model; 
      DSColumnList = new List<DSGridColumn>(); 
     } 

     public DSGridHelper3<T> AddColumn(Expression<Func<T, object>> property) 
     { 
      string columnName = (property.Body as MemberExpression).Member.Name; 
      DSGridColumn DSGC = new DSGridColumn(); 
      DSGC.ColumnName = columnName; 
      DSGC.HeaderText = columnName; 
      DSColumnList.Add(DSGC); 

      return this; 
     } 

     public MvcHtmlString ToMvcString() 
     { 
      sb.Append("<table>"); 
      sb.Append("<tr>"); 
      sb.Append("<td>"); 
      sb.Append("hello world within a table"); 
      sb.Append(@"</td>"); 
      sb.Append("<td>"); 
      sb.Append("hello world within a table"); 
      sb.Append(@"</td>"); 
      sb.Append(@"</tr>"); 
      sb.Append(@"</table>"); 


      return new MvcHtmlString(sb.ToString()); 

     } 
    } 

更新2

如果你想手动插入不同类型的(也许是因为你会从ViewData的获取表中的数据量小,而不是页面的模型),那么这里是一些代码:

查看:

@(Html.DSGridFor3<DanSoftware.MVC.Areas.Errors.Code.ELMAH_Error>().AddColumn(x => x.Message).ToMvcString();) 

为DSGridHelper替代签名...帮助

public static DSGridHelper3<T> DSGridFor3<T>(this HtmlHelper htmlHelper) 
     { 
      return new DSGridHelper3<T>(htmlHelper); 
     } 

附加构造:

public DSGridHelper3(HtmlHelper htmlHelper) 
     { 
      _htmlHelper = htmlHelper; 
      // _dataList = htmlHelper.ViewData.Model; 
      DSColumnList = new List<DSGridColumn>(); 
     } 

希望这可以帮助别人,谢谢Justin!

+0

但是在这里你会被警告 - 小心使用列名提取 - 它不会一直工作。数据库基本上是Elmah表。试图获取ErrorID时,表达式实际上是{x => Convert(x.ErrorId)},它在上面的代码中失败。解决方案欢迎来到这里! – 2011-06-06 21:09:46

+0

在这里打开一个单独的问题http://stackoverflow.com/questions/6269822/linq-member-expression-getting-column-name – 2011-06-07 18:21:07

回答

2

我没有Visual Studio与我,但我会采取刺... ...

我会在DsGridFor方法或AddColumn方法中将数据集作为数据类型。这将允许您从集合中发送Strongly-typed参数。假设你想要的AddColumn一个通用的方法对某个集合与访问类的属性VS的收集方法,它会是这个样子(只是一个例子):

public static DSGridHelper<T> AddColumn<T>(this HtmlHelper<IEnumerable<T>> htmlHelper, Expression<Func<T, object>> property) where T : class 
    { 
     string columnName = (property.Body as MemberExpression).Member.Name; 

     DSGridColumn DSGC = new DSGridColumn(); 
     DSGC.ColumnName = ColumnName; 
     DSGC.HeaderText = HeaderText ?? ColumnName; 
     DSColumnList.Add(DSGC); 

     return this; 
    } 

您的具体情况,对新机一个DsGridHelper类我可以明确的调整的型号类型,然后再添加过载,我去:

public static DSGridHelper<T> DSGridFor<T>(this HtmlHelper<IEnumerable<T>> htmlHelper) where T : class 
    { 
     return new DSGridHelper<T>(htmlHelper); 
    } 

然后我DsGridHelper可能是这个样子:

public class DsGridHelper<T> 
{ 
    private HtmlHelper _htmlHelper; 
    private IEnumerable<T> _dataList; 

    public DsGridHelper(HtmlHelper<IEnumerable<T>> htmlHelper) 
    { 
     _htmlHelper = htmlHelper; 
     _dataList = htmlHelper.ViewData.Model; 
    } 

    public DsGridHelper<T> AddColumn(Expression<Func<T, object>> property) 
    { 
     string columnName = (property.Body as MemberExpression).Member.Name; 
     DSGridColumn DSGC = new DSGridColumn(); 
     DSGC.ColumnName = ColumnName; 
     DSGC.HeaderText = HeaderText ?? ColumnName; 
     DSColumnList.Add(DSGC); 

     return this; 
    } 
} 
+0

酷 - 我会尝试今晚 - 谢谢! – 2011-06-06 11:38:02

+0

代码主要是工作(SUPER)intellisense明智的,但在运行时遇到错误:传入字典的模型项类型为'System.Data.Objects.ObjectQuery'1 [System.String]',但此字典需要一个'System.Collections.Generic.IEnumerable'1 – 2011-06-06 20:29:58

+0

类型的模型项我假设它在你的网格类的某个地方,也许当你添加你的列?我不得不多看看你的代码,看看造成这个问题的原因。 – 2011-06-06 20:49:31