【问题标题】:Creating custom Html Helper: MyHelperFor创建自定义 Html Helper:MyHelperFor
【发布时间】:2013-08-27 17:41:32
【问题描述】:

我想创建一个可以像这样使用的助手

@Html.MyHelperFor(m => m.Name)

这应该返回例如

<span name="Name" data-something="Name"></span>

如果是@Html.MyHelperFor(m => m.MailID) 这应该返回

<span name="MailID" data-something="MailID"></span>

我认为我应该能够访问辅助方法中的属性名称来制作这种类型的帮助器。

我该怎么做?

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 razor


    【解决方案1】:

    您可以执行类似的操作(以下内容也将采用额外的 HTML 属性)。

    public static MvcHtmlString MyHelperFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes = null)
    {
        var data = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
        string propertyName = data.PropertyName;
        TagBuilder span = new TagBuilder("span");
        span.Attributes.Add("name", propertyName);
        span.Attributes.Add("data-something", "something");
    
        if (htmlAttributes != null)
        {
            var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
            span.MergeAttributes(attributes);
        }
    
        return new MvcHtmlString(span.ToString());
    }
    

    【讨论】:

    • 这应该添加到命名空间 System.Web.Mvc.Html 下的静态类中。
    • @BornToCode 你知道,我更喜欢在它们引用的类型的命名空间下编写的扩展,否则如果其他开发人员不知道它们,他们就不会使用它们,因为他们需要知道关于它们以及它们所在的命名空间,以便添加引用并使用它。
    • 问题要求 data-something="MailID" 您将其设置为“某物”。该示例需要展示如何获取表达式的值,而不仅仅是属性的名称。
    • 聚会有点晚了——但是——你可以编译expression并传入helper.Model以获得TValue的实例。在代码中:TValue value = expression.Compile().Invoke(helper.Model);
    【解决方案2】:

    您可以像这样使用ModelMetadata 中的FromLambaExpression 方法:

    namespace System.Web.Mvc.Html
    {
        public static class CustomHelpers
        {
            public static MvcHtmlString MyHelperFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
            {
                var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
                var name = metaData.PropertyName;
                // create your html string, you could defer to DisplayFor to render a span or
                // use the TagBuilder class to create a span and add your attributes to it
                string html = "";
                return new MvcHtmlString(html);
            }
        }
    }
    

    ModelMetadata 类位于 System.Web.Mvc 命名空间中。 FromLambdaExpression 方法是内置助手使用的,因此您可以确保您的助手将与内置助手功能相同。通过将CustomHelpers 类放在System.Web.Mvc.Html 命名空间中,您可以像访问其他助手一样访问您的助手,即@Html.MyHelperFor()。

    【讨论】:

      【解决方案3】:

      这应该可以帮助您入门。此函数直接返回属性名称,但您应该能够通过一些工作将其转换为您正在寻找的扩展名。此示例具有正确的方法签名和对 ExpressionHelper 的调用以获取您的属性的名称。

          public static MvcHtmlString MyHelperFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression)
          {
              string expressionName = ExpressionHelper.GetExpressionText(expression);
      
              return new MvcHtmlString(expressionName);
          }
      

      【讨论】:

        【解决方案4】:

        按照 mattytommo 的回答,这很好用,但在与复杂对象一起使用时只有一个小问题,例如,如果您将此代码用于 EditorTemplate 中的属性。

        而不是

        var data = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
        string propertyName = data.PropertyName;
        

        如果使用MVC4,可以改成

        var propertyName = helper.NameFor(expression);
        

        或用于 MVC3 及以下

        var propertyName = expression.Body.ToString();
        propertyName = propertyName.Substring(propertyName.IndexOf(".") + 1);
        if (!string.IsNullOrEmpty(helper.ViewData.TemplateInfo.HtmlFieldPrefix))
            propertyName = string.Format("{0}.{1}", helper.ViewData.TemplateInfo.HtmlFieldPrefix, propertyName);
        

        完整代码:

            public static MvcHtmlString MyHelperFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes = null)
            {
                var propertyName = expression.Body.ToString();
                propertyName = propertyName.Substring(propertyName.IndexOf(".") + 1);
                if (!string.IsNullOrEmpty(helper.ViewData.TemplateInfo.HtmlFieldPrefix))
                    propertyName = string.Format("{0}.{1}", helper.ViewData.TemplateInfo.HtmlFieldPrefix, propertyName);
        
                TagBuilder span = new TagBuilder("span");
                span.Attributes.Add("name", propertyName);
                span.Attributes.Add("data-something", propertyName);
        
                if (htmlAttributes != null)
                {
                    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
                    span.MergeAttributes(attributes);
                }
        
                return new MvcHtmlString(span.ToString());
            }
        

        【讨论】:

          猜你喜欢
          • 2012-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-14
          • 2021-11-27
          • 1970-01-01
          • 1970-01-01
          • 2017-06-21
          相关资源
          最近更新 更多