什么是Html.EditorFor

时间:2018-01-18 13:23:42

标签: asp.net-core asp.net-core-tag-helpers

如果我对字符串类型的属性使用Html.EditorFor,那么生成的元素默认为<input>类型&#39; text&#39;。

或者,如果属性具有属性[DataType(DataType.MultilineText)],则Html.EditorFor会生成<textarea>

但是,如果我使用标记帮助程序,那么我必须为自己选择元素类型,例如<input asp-for='MyProperty' />。这可以使用有关该属性的信息来确定输入的类型(文本,日期,电子邮件等),但总是生成<input>,而不是<textarea>,即使我有{ {1}}属性。

这似乎违背了我可以在一个地方进行从单线到多线的改变的想法:模型。现在我必须经历所有相关的观点并自己做出改变。

在我看来,我完全有可能编写自己的标记助手,可以查看属性属性并决定是生成[DataType]还是<input>,但我无法找到任何对预定义的引用。

是否有这样的预定义标签助手,如果没有,是否有原因?

4 个答案:

答案 0 :(得分:0)

对于它的价值,你讨论的一些内容实际上是InputTagHelper的一部分。它将根据属性类型(bool的复选框等)在不同的输入类型之间动态切换。但是,正如您所指出的,它只会生成一个输入,因为它明确地是一个输入标记。 textareas有一个完全不同的taghelper。 技术上可以创建一个自定义标记助手来实现你想要的东西,但是有很多工作要做。有关参考,请参阅source for InputTagHelper。目前,无法从标记帮助程序调用其他标记帮助程序,因此您需要将InputTagHelper的整个代码与TextAreaTagHelper的代码基本合并到自定义标记帮助程序中。通过从InputTagHelper继承自定义标记帮助程序,然后覆盖Process以调用base.Process()然后自定义输出,您可以节省一些工作。然而,再一次,这比这里的简单答案更复杂。

长而短,是的,这可以通过自定义标记帮助程序实现,但它需要一些工作。就个人而言,我认为这是一个比它值得多的工作,考虑到它只是一个案例:使用textarea切换输入以进行多行输入,如果您愿意,技术上仍然可以使用EditorFor

如果你想沿着这条路走下去,微软有an article/tutorial这将给你一个良好的开端。除此之外,只需研究现有助手的来源。

答案 1 :(得分:0)

到目前为止,没有任何标记帮助程序可以实现此目的,但您可以创建类似于此的标记帮助程序。

    [HtmlTargetElement("editor-for")]
    public class EditorForTagHelper : TagHelper
    {
        private const string TemplateValuesDictionaryName = "template-all-data";
        private const string HtmlAttributesDictionaryName = "html-all-data";

        private IDictionary<string, object> _templateValues;
        private IDictionary<string, string> _htmlAttributes;

        public ModelExpression For
        {
            get; set;
        }

        /// <summary>
        /// Display template name  to use for rendering
        /// </summary>
        public string Template
        {
            get; set;
        }

        /// <summary>
        /// Additional parameters for the template.
        /// </summary>
        [HtmlAttributeName(TemplateValuesDictionaryName, DictionaryAttributePrefix = "template-")]
        public IDictionary<string, object> TemplateValues
        {
            get
            {
                if (_templateValues == null)
                    _templateValues = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

                return _templateValues;
            }
            set
            {
                _templateValues = value;
            }
        }

        /// <summary>
        /// Additional htmlattributes for the control template
        /// </summary>
        [HtmlAttributeName(HtmlAttributesDictionaryName, DictionaryAttributePrefix = "html-")]
        public IDictionary<string, string> HtmlAttributes
        {
            get
            {
                if (_htmlAttributes == null)
                    _htmlAttributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

                return _htmlAttributes;
            }
            set
            {
                _htmlAttributes = value;
            }
        }


        [HtmlAttributeNotBound]
        [ViewContext]
        public ViewContext ViewContext
        {
            get; set;
        }

        /// <summary>
        /// Creates a new <see cref="DisplayForTagHelper"/>.
        /// </summary>        
        public EditorForTagHelper()
        {
        }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
                throw new ArgumentNullException(nameof(context));

            if (output == null)
                throw new ArgumentNullException(nameof(output));


            if (For != null)
            {
                TemplateValues.AddOrUpdate("htmlAttributes", HtmlAttributes.ToDictionary(e => e.Key, e => (object)e.Value));
                var control = ViewContext.GenerateEditor(For,For.Name, Template, TemplateValues);
                output.Content.AppendHtml(control);
            }
        }
    }

答案 2 :(得分:0)

使用等同于Html.EditorFor的标记帮助器的新方法仅是通过在标记帮助器内部使用旧的HtmlHelper。看看这个博客,您可能会找到所需的内容或使用我的代码。 http://blog.techdominator.com/article/using-html-helper-inside-tag-helpers.html

 [HtmlTargetElement("editor", TagStructure = TagStructure.WithoutEndTag, 
    Attributes = ForAttributeName + "," + TemplateAttributeName)]
public class EditorTagHelper : TagHelper
{
    private IHtmlHelper _htmlHelper;

    private const string ForAttributeName = "asp-for";
    private const string TemplateAttributeName = "asp-template";

    [HtmlAttributeName(ForAttributeName)]
    public ModelExpression For { get; set; }


    [HtmlAttributeName(TemplateAttributeName)]
    public string Template { get; set; }

    [ViewContext]
    [HtmlAttributeNotBound]
    public ViewContext ViewContext { get; set; }

    public EditorTagHelper(IHtmlHelper htmlHelper)
    {
        _htmlHelper = htmlHelper;
    }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        if (output == null)
            throw new ArgumentNullException(nameof(output));

        output.SuppressOutput();

        (_htmlHelper as IViewContextAware).Contextualize(ViewContext);

        output.Content.SetHtmlContent(_htmlHelper.Editor(For.Name, Template));

        await Task.CompletedTask;
    }
}

答案 3 :(得分:0)

扩展了“ Owusu王子”提供的答案,我对其进行了修改,以便“ Template”属性是可选的:

[HtmlTargetElement("editor", TagStructure = TagStructure.WithoutEndTag,
    Attributes = ForAttributeName)]
public class EditorTagHelper : TagHelper
{
    private readonly IHtmlHelper _htmlHelper;

    private const string ForAttributeName = "asp-for";
    private const string TemplateAttributeName = "asp-template";

    [HtmlAttributeName(ForAttributeName)]
    public ModelExpression For { get; set; }


    [HtmlAttributeName(TemplateAttributeName)]
    public string Template { get; set; }

    [ViewContext]
    [HtmlAttributeNotBound]
    public ViewContext ViewContext { get; set; }

    public EditorTagHelper(IHtmlHelper htmlHelper)
    {
        _htmlHelper = htmlHelper;
    }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        if (output == null)
            throw new ArgumentNullException(nameof(output));

        if (!output.Attributes.ContainsName(nameof(Template)))
        {
            output.Attributes.Add(nameof(Template), Template);
        }

        output.SuppressOutput();

        (_htmlHelper as IViewContextAware).Contextualize(ViewContext);

        output.Content.SetHtmlContent(_htmlHelper.Editor(For.Name, Template));

        await Task.CompletedTask;
    }
}

将使用类似这样的内容:

<editor asp-for="MyModel.EmailAddress"/>

相当于:

@Html.EditorFor(x => x.MyModel.EmailAddress)

在我的用法示例中,我没有指定模板,因此ASP.NET将查找与我的“ EmailAddress”属性的类型匹配的模板。如果我想指定一个模板,则可以这样使用它:

<editor asp-for="MyModel.EmailAddress" asp-template="MyEmailTemplate"/>