ASP.NET MVC: Why can't I set ShowForEdit model

2019-05-12 17:54发布

Why can't I set ShowForEdit model metadata with an attribute?

It seems that the only attribute provided to alter this is [ScaffoldColumn], which sets both ShowForEdit and ShowForDisplay, which is not what I want to do. I want to be able to annotate the two separately from on my model.

2条回答
叼着烟拽天下
2楼-- · 2019-05-12 18:08

What is the type of property you are applying it to? If we use Reflector, we can discover that the ShowForEdit and ShowForDisplay properties are used in the following functions:

ShowForEdit: System.Web.Mvc.Html.DefaultEditorTemplates.ShouldShow(...)

ShowForDisplay: System.Web.Mvc.Html.DefaultDisplayTemplates.ShouldShow(...)

The definition of these methods is:

private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo)
{
  return (((metadata.ShowForEdit && (metadata.ModelType != typeof(EntityState))) && !metadata.IsComplexType) && !templateInfo.Visited(metadata));
}

private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo)
{
  return (((metadata.ShowForDisplay && (metadata.ModelType != typeof(EntityState))) && !metadata.IsComplexType) && !templateInfo.Visited(metadata));
}

Ignoring the obvious property check (metadata.ShowForX), you can see that it is checking whether the model is an instance of EntityState (probably isn't), and then a check for metadata.IsComplexType.

We can look at the IsComplexType property here:

public virtual bool IsComplexType
{
  get
  {
    return !TypeDescriptor.GetConverter(this.ModelType).CanConvertFrom(typeof(string));
  }
}

What that is saying is that it will return true if the model cannot be converted from a string, and in the ShouldShow() methods, it will show if it is not a complex type, i.e., the value CAN be converted from a string.

What you will need to do, is create a TypeConverter that can convert a string, to the model, e.g:

A model:

[TypeConverter(typeof(ItemConverter))]
public class Item 
{
  #region Properties
  public string Text { get; set; }
  #endregion
}

And a converter:

public class ItemConverter : TypeConverter
{
  #region Methods
  public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
  {
    if (sourceType == typeof(string))
      return true;

    return base.CanConvertFrom(context, sourceType);
  }

  public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
  {
    if (value.GetType() == typeof(string)) 
    {
      return new Item { Text = (string)value };
    }

    return base.ConvertFrom(context, culture, value);
  }
  #endregion
}

With that in place, try it again and see if that helps.

查看更多
Fickle 薄情
3楼-- · 2019-05-12 18:10

Because it is not supported out of the box. AFAIK the reason is because the dataannotations attribute that support this functionality are in .net 4.0 and in order to make MVC 3.5 and 4.0 compatible they had to be excluded.

The easiest way to fix this is to have to implement your own Edit/Show attribute as demonstrated in this Question/Answer:

Showing Different fields in EditorForModel vs. DisplayForModel modes in MVC2

查看更多
登录 后发表回答