2010-06-02 4 views
10

Tengo un modelo de vista que tiene un campo int StateID y un campo string StateName así:Muestra Diversos campos en EditorForModel vs. modos DisplayForModel en MVC2

public class DepartmentViewModel : BaseViewModel, IModelWithId 
{ 
    // only show in edit mode 
    public int StateId { get; set; } 

    // only show in display mode 
    public string StateName { get; set; } 
} 

tengo una única vista lectura que utiliza DisplayForModel y una vista de actualización que usa EditorForModel. Quiero la vista DisplayForModel para mostrar la propiedad StateName, y la vista EditorForModel utilizar la propiedad StateID (en realidad estoy prestación de un DropDownList basado en esto).

no he sido capaz de averiguar cómo decorar mis propiedades ViewModel para crear este comportamiento.

Respuesta

14

que quería una solución que era más genérico, por lo que creó un nuevo atributo :

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 
public sealed class RenderModeAttribute : Attribute 
{ 
    public RenderMode RenderMode { get; set; } 

    public RenderModeAttribute(RenderMode renderMode) 
    { 
     RenderMode = renderMode; 
    } 
} 

public enum RenderMode 
{ 
    Any, 
    EditModeOnly, 
    DisplayModeOnly 
} 

e incluyó el siguiente código en mi DataAnnotationsModelMetadataProvider personalizado:

var renderModeAttribute = attributes.OfType<RenderModeAttribute>(); 
if (renderModeAttribute.Any()) 
{ 
    var renderMode = renderModeAttribute.First().RenderMode; 
    switch (renderMode) 
    { 
     case RenderMode.DisplayModeOnly: 
      metadata.ShowForDisplay = true; 
      metadata.ShowForEdit = false; 
      break; 
     case RenderMode.EditModeOnly: 
      metadata.ShowForDisplay = false; 
      metadata.ShowForEdit = true; 
      break; 
    } 
} 

Así que solo pude decorar mi modelo como así:

public class DepartmentViewModel  
{  
    [RenderMode(RenderMode.EditModeOnly)] 
    public int StateId { get; set; }  

    [RenderMode(RenderMode.DisplayModeOnly)]  
    public string StateName { get; set; }  
} 
+0

¿Cómo se implementa la costumbre DataAnnotationsModelMetadataProvider? Gracias. – UpTheCreek

+0

@UpTheCreek - Heredar de DataAnnotationsModelMetadataProvider. http://weblogs.asp.net/seanmcalinden/archive/2010/06/11/custom-asp-net-mvc-2-modelmetadataprovider-for-using-custom-view-model-attributes.aspx – CodeGrue

+2

Gracias por compartir su solución. Sin embargo, sería útil si pudieras dar detalles de dónde debe ir el segundo fragmento de código (supongo que tenemos que anular CreateMetadata y ponerlo allí) y también cómo registrar nuestro DataAnnotationsModelMetadataProvider una vez creado. – mutex

0

sobreescribir las plantillas:

En ~/Shared/EditorTemplates/DepartmentViewModel.ascx puesto:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Namespace.DepartmentViewModel>" %> 
<%= Html.LabelFor(x => x.StateId) %> 
<%= Html.TextBoxFor(x => x.StateId) %> 

Y en su ~/Shared/DisplayTemplates/DepartmentViewModel.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Namespace.DepartmentViewModel>" %> 
<div><%= Html.Encode(Model.StateName) %></div> 
1

Aquí es mi proveedor personalizado, agrego un modo Ninguno

render
public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider 
{ 
    protected override ModelMetadata CreateMetadata(System.Collections.Generic.IEnumerable<System.Attribute> attributes, System.Type containerType, System.Func<object> modelAccessor, System.Type modelType, string propertyName) 
    { 
     var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); 

     var renderModeAttribute = attributes.OfType<RenderModeAttribute>(); 
     if (renderModeAttribute.Any()) 
     { 
      var renderMode = renderModeAttribute.First().RenderMode; 
      switch (renderMode) 
      { 
       case RenderMode.DisplayModeOnly: 
        metadata.ShowForDisplay = true; 
        metadata.ShowForEdit = false; 
        break; 

       case RenderMode.EditModeOnly: 
        metadata.ShowForDisplay = false; 
        metadata.ShowForEdit = true; 
        break; 

       case RenderMode.None: 
        metadata.ShowForDisplay = false; 
        metadata.ShowForEdit = false; 
        break; 
      } 
     } 

     return metadata; 
    } 
} 
17

Un comentario en la respuesta de CodeGrue.

Haga que el atributo herede IMetadataAware. De esta forma, no es necesario que construya su propio DataAnnotationsModelMetadataProvider.

El nuevo atributo se convertiría en algo como:

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

    public RenderModeAttribute(RenderMode renderMode) 
    { 
     RenderMode = renderMode; 
    } 

    public void OnMetadataCreated(ModelMetadata metadata) 
    { 
     switch (RenderMode) 
     { 
      case RenderMode.DisplayModeOnly: 
       metadata.ShowForDisplay = true; 
       metadata.ShowForEdit = false; 
       break; 

      case RenderMode.EditModeOnly: 
       metadata.ShowForDisplay = false; 
       metadata.ShowForEdit = true; 
       break; 

      case RenderMode.None: 
       metadata.ShowForDisplay = false; 
       metadata.ShowForEdit = false; 
       break; 
     } 
    } 
} 

public enum RenderMode 
{ 
    Any, 
    EditModeOnly, 
    DisplayModeOnly 
} 
Cuestiones relacionadas