2011-06-05 56 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