@Html.DisplayFor 的 MVC6 替代品

Posted

技术标签:

【中文标题】@Html.DisplayFor 的 MVC6 替代品【英文标题】:MVC6 alternative to @Html.DisplayFor 【发布时间】:2015-09-19 18:10:53 【问题描述】:

MVC6 引入了 Tag Helper,与使用 @html.EditorFor 等相比,这是一种更好的方法。但是我还没有找到任何可以替代 @Html.DisplayFor 的 Tag Helper。

当然,我可以直接在 Razor 页面上使用变量,例如 @Model.BookingCode。但这不允许控制格式。

对于 MVC6,在概念上显示模型属性值的正确方法是什么?

【问题讨论】:

【参考方案1】:

@Html.DisplayFor 仍然存在并且仍然可以使用。

HtmlHelpers 和 TagHelpers 之间的区别在于,HtmlHelpers 选择为您呈现哪些 html 元素,而 TagHelpers 使用您自己添加的 html 标签,因此您可以更全面地控制使用的 html 元素。您确实可以使用带有 HtmlHelpers 的模板对标记进行一些控制,但您可以使用 TagHelpers 进行更多控制。

所以你应该考虑我想用什么 html 标记来包装这个模型属性,并使用 @Model.Property 在属性本身周围添加标记,周围有一些标记,或者如果你愿意让帮手决定。

【讨论】:

我可以,而且有效。问题是,虽然 MVC6 为我们提供了更好、更直观的 Html.EditorFor 替代方案,但顺理成章地认为它也会为 Html.DisplayFor 提供更好的替代方案。可能我只是缺少一个。 是的,TagHelpers 对更复杂的事情更有意义。然而,仅仅显示它可能是 或 这对我来说非常有意义。甚至是像 这样的非 HTML。这样 Razor 代码可以更清晰,没有 lambda 表达式等。 我仍然认为 MVC6 缺少一种显示属性格式化值的好方法,同时我可以控制 html 标签。但这并不重要,因为 DisplayFor 仍然有效。无论如何,答案很明确——没有 TagHelper 只显示值。谢谢! @SergeyKandaurov,我完全同意你的看法。对我来说,我们没有 DisplayFor 的 taghelper 是没有意义的。将 这确实有意义,因为标签只是一个标签,DisplayFor 可以输出任何内容。海事组织【参考方案2】:

您可以创建自己的标签助手

namespace MyDemo.TagHelpers

    [HtmlTargetElement("p", Attributes = ForAttributeName)]
    public class DisplayForTagHelper : TagHelper
    
        private const string ForAttributeName = "asp-for";

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

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

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

            var text = For.ModelExplorer.GetSimpleDisplayText();

            output.Content.SetContent(text);
        
    

在视图中添加使用它:

<p asp-for="MyProperty" class="form-control-static"></p>

【讨论】:

这似乎是显示一个属性的内容而不是显示属性? 这将显示显示属性: var text = For.ModelExplorer.Metadata.DisplayName ?? For.ModelExplorer.Metadata.PropertyName; span 不会比p 更有意义吗? @DavidCumps @Html.DisplayFor 用于显示内容; @HTML.DisplayNameFor 用于显示已在 label 上具有标签助手的 DisplayName。 @DavidCumps DisplayFor 应该显示内容,DisplayNameFor 应该显示名称。【参考方案3】:

我一直把它用作显示标签助手。

[HtmlTargetElement("*", Attributes = ForAttributeName)]
public class DisplayForTagHelper : TagHelper

    private const string ForAttributeName = "asp-display-for";
    private readonly IHtmlHelper _html;

    public DisplayForTagHelper(IHtmlHelper html)
    
        _html = html;
    

    [HtmlAttributeName(ForAttributeName)]
    public ModelExpression Expression  get; set; 

    public IHtmlHelper Html
    
        get
        
            (_html as IViewContextAware)?.Contextualize(ViewContext);
            return _html;
        
    

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

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

        var type = Expression.Metadata.UnderlyingOrModelType;
        if (type.IsPrimitive)
        
            output.Content.SetContent(Expression.ModelExplorer.GetSimpleDisplayText());
        
        // Special Case for Personal Use
        else if (typeof(Dictionary<string, string>).IsAssignableFrom(type))
        
            output.Content.SetHtmlContent(Html?.Partial("Dictionary", Expression.ModelExplorer.Model));
        
        else
        
            var htmlContent = Html.GetHtmlContent(Expression);
            output.Content.SetHtmlContent(htmlContent);
        
    


public static class ModelExpressionExtensions

    public static IHtmlContent GetHtmlContent(this IHtmlHelper html, ModelExpression expression)
    
        var ViewEngine = html.ViewContext.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
        var BufferScope = html.GetFieldValue<IViewBufferScope>();
        var htmlContent = new TemplateBuilder(ViewEngine, BufferScope, html.ViewContext, html.ViewContext.ViewData, expression.ModelExplorer, expression.Name, null, true, null).Build();
        return htmlContent;
    

    public static TValue GetFieldValue<TValue>(this object instance)
    
        var type = instance.GetType(); 
        var field = type.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).FirstOrDefault(e => typeof(TValue).IsAssignableFrom(e.FieldType));
        return (TValue)field?.GetValue(instance);
    

【讨论】:

【参考方案4】:
try below code

public class movie

    public int ID  get; set; 
    [DisplayName("Movie Title")]
    public string Title  get; set; 

///////////////////////////////////////////////////

@model IEnumerable<MvcMovie.Models.Movie>

<h1>Show List Movies</h1>
<label asp-for="ToList()[0].Title">< /label>
@foreach (var movie in Model)

    @movie.Title

【讨论】:

这很好,但它没有回答所要求的问题。这是@Html.DisplayNameFor 的替代品,而不是要求的@Html.DisplayFor

以上是关于@Html.DisplayFor 的 MVC6 替代品的主要内容,如果未能解决你的问题,请参考以下文章

MVC3 Html.DisplayFor -- 是不是可以让这个控件生成一个 ID?

在 MVC5 中使用 Html.DisplayFor() 的日期格式

我想了解 @Html.DisplayFor(modelItem => item.FirstName) 中的 lambda 表达式

单击时 - 使 @Html.DisplayFor 成为可编辑的文本字段

SQL Server 数据库集,配置集 - 但来自数据库的数据未使用 @Html.DisplayFor<>() 显示?

为啥我的 DisplayFor 没有循环通过我的 IEnumerable<DateTime>?