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

谁说我不能喝 提交于 2019-11-29 15:03:36

问题


I am reading up on ASP.NET MVC and all of it's fun uses and I just found out about DataTemplates.

In my hurry to test this thing out, I converted one of my simpler models over to using @Html.DisplayForModel() and @Html.EditForModel() and it worked like a lucky charm that it is :)

One thing that I immediately found out though was that I could not easily define a field to show up on display views but not be present at all for editing...


回答1:


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.




回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/5583464/how-to-exclude-a-field-from-html-editformodel-but-have-it-show-using-html-dis

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