MVC6 alternative to @Html.DisplayFor

喜夏-厌秋 提交于 2019-12-03 15:08:11

问题


MVC6 introduces Tag Helpers which is a better way compared to using @Html.EditorFor, etc. However I have not found any Tag Helper that would be an alternative to @Html.DisplayFor.

Of course I can use a variable directly on a Razor page, such as @Model.BookingCode. But this does not allow to control formatting.

With MVC6, what's conceptually correct way for displaying a value of a model property?


回答1:


You can create your own tag helper

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

Add use it in view:

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



回答2:


@Html.DisplayFor still exists and can still be used.

The difference between HtmlHelpers and TagHelpers is that HtmlHelpers choose which html elements to render for you whereas TagHelpers work with html tags that you add yourself so you have more full control over what html element is used. You do have some control over the markup using templates with HtmlHelpers but you have more control with TagHelpers.

So you should think in terms of what html markup do I want to wrap this model property in and add that markup around the property itself using @Model.Property with some markup around it or continue using DisplayFor if you prefer to let the helper decide.




回答3:


I have been using this as a display tag helper.

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


来源:https://stackoverflow.com/questions/32671644/mvc6-alternative-to-html-displayfor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!