How to exclude a field from @Html.EditForModel() but have it show using Html.DisplayForModel()

假装没事ソ 提交于 2019-11-30 09:56:06

You can make use of IMetadataAware interface an create attribute which will set ShowForEdit and ShowForDislay in Metadata:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class TemplatesVisibilityAttribute : Attribute, IMetadataAware
{
    public bool ShowForDisplay { get; set; }

    public bool ShowForEdit { get; set; }

    public TemplatesVisibilityAttribut()
    {
        this.ShowForDisplay = true;
        this.ShowForEdit = true;
    }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        if (metadata == null)
        {
            throw new ArgumentNullException("metadata");
        }

        metadata.ShowForDisplay = this.ShowForDisplay;
        metadata.ShowForEdit = this.ShowForEdit;
    }

}

Then you can attach it to your property like this:

public class TemplateViewModel
{
  [TemplatesVisibility(ShowForEdit = false)]
  public string ShowForDisplayProperty { get; set; }

  public string ShowAlwaysProperty { get; set; }
}

And this is all you need.

You could write a custom metadata provider and set the ShowForEdit metadata property. So start with a custom attribute:

public class ShowForEditAttribute : Attribute
{
    public ShowForEditAttribute(bool show)
    {
        Show = show;
    }

    public bool Show { get; private set; }
}

then a custom model metadata provider:

public class MyModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes,
        Type containerType, 
        Func<object> modelAccessor, 
        Type modelType, 
        string propertyName
    )
    {
        var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        var sfea = attributes.OfType<ShowForEditAttribute>().FirstOrDefault();
        if (sfea != null)
        {
            metadata.ShowForEdit = sfea.Show;
        }
        return metadata;
    }
}

then register this provider in Application_Start:

ModelMetadataProviders.Current = new MyModelMetadataProvider();

and finally decorate:

public class MyViewModel
{
    [ShowForEdit(false)]
    public string Prop1 { get; set; }

    public string Prop2 { get; set; }
}

Now if in your view you have:

@model MyViewModel

<h2>Editor</h2>
@Html.EditorForModel()

<h2>Display</h2>
@Html.DisplayForModel()

the Prop1 property won't be included in the editor template.

Remark: you could do the same with the ShowForDisplay metadata property.

Can you display each of the fields you want using Html.DisplayTextbox or one of the other options? That way you can also customize the appearance and labels referring to the field.

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