如果我对字符串类型的属性使用Html.EditorFor
,那么生成的元素默认为<input>
类型&#39; text&#39;。
或者,如果属性具有属性[DataType(DataType.MultilineText)]
,则Html.EditorFor
会生成<textarea>
。
但是,如果我使用标记帮助程序,那么我必须为自己选择元素类型,例如<input asp-for='MyProperty' />
。这可以使用有关该属性的信息来确定输入的类型(文本,日期,电子邮件等),但总是生成<input>
,而不是<textarea>
,即使我有{ {1}}属性。
这似乎违背了我可以在一个地方进行从单线到多线的改变的想法:模型。现在我必须经历所有相关的观点并自己做出改变。
在我看来,我完全有可能编写自己的标记助手,可以查看属性属性并决定是生成[DataType]
还是<input>
,但我无法找到任何对预定义的引用。
是否有这样的预定义标签助手,如果没有,是否有原因?
答案 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"/>