views:

166

answers:

1

Iv wrote an MetaDataProvider like the one below and am using it in conjunction with Editor templates. The DisplayName is working correctly, but for some reason the ShowForEdit value it not having any effect. Any ideas?

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

            metadata.DisplayName = "test";

            metadata.ShowForEdit = false;
            metadata.ShowForDisplay = false;
            metadata.HideSurroundingHtml = true;

            return metadata;
        }
}
+1  A: 

This seems similar to #3013051 (http://stackoverflow.com/questions/3013051/asp-net-mvc-why-cant-i-set-showforedit-model-metadata-with-an-attribute/3014278#3014278), so I'll replicate my answer here:

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 those 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 intstance 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.

Matthew Abbott