【问题标题】:MVC3 razor based htmlhelper with lambda field expressions based on model基于 MVC3 razor 的 htmlhelper,带有基于模型的 lambda 字段表达式
【发布时间】:2011-06-05 15:55:13
【问题描述】:

我正在 MVC 中创建一个流畅的 HtmlHelper - 创建一个基于 HTML 的网格。 我知道 mvc contrib 和 WebGrid - 但我正在制作自己的并且有一个特定的问题:

我必须输入这个:

@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().Message 但我真的只需要 x=>x.Message 来识别列。

感谢您的帮助。

更新

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

查看:

@(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 的替代签名 ...helper

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>();
        }

希望这对某人有所帮助并感谢贾斯汀!

【问题讨论】:

  • 但是在这里警告你们——小心提取列名——它并不总是有效。该数据库基本上是 Elmah 表。尝试获取 ErrorID 时,表达式实际上是 {x => Convert(x.ErrorId)} 在上面的代码中失败。解决方案也欢迎使用!
  • 在这里打开了一个单独的问题stackoverflow.com/questions/6269822/…

标签: asp.net-mvc-3 lambda grid expression


【解决方案1】:

我没有 Visual Studio,但我会尝试一下...

我会在您的DsGridFor 方法或AddColumn 方法中将集合作为数据类型。这将允许您从集合中发送强类型参数。假设您想要一个通用方法 AddColumn 用于访问类属性与集合方法的给定集合,它看起来像这样(只是一个示例):

    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;
    }
}

【讨论】:

  • 代码大部分工作(超级)智能感知,但在运行时遇到错误:传递到字典中的模型项的类型为 'System.Data.Objects.ObjectQuery1[System.String]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1跨度>
  • 我假设它在您的网格类中的某个地方,也许是在您添加列时?我必须查看更多代码才能了解导致问题的原因。
  • 成功!我正在做一些非常愚蠢的事情,哈哈。如果将正确的模型类型传递给视图,它会有所帮助。 脸红。我会在一秒钟内发布我的代码。顺便说一句 - 你是个天才!
  • 看起来不错,很高兴能帮上忙。我会看看你遇到的 Elmah 问题。
  • 我刚刚想到的另一个问题 - 我如何最好地将不同的模型传递到您帮助我解决的实现中?我可能有两个表(可能是较小的一个),我使用 ViewData 而不是模型将它们添加到页面中。再次感谢贾斯汀!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-04
  • 2013-01-07
  • 2013-07-19
  • 2020-07-31
  • 2018-02-28
相关资源
最近更新 更多