2010-06-02 7 views
10

Mam ViewModel, który ma pole int StateID i string StateName pole tak:Pokazuje różnych dziedzinach w porównaniu z trybami DisplayForModel EditorForModel w 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; } 
} 

mam przeczytany Zobacz tylko, że używa DisplayForModel oraz widok aktualizacji który używa EditorForModel. Chcę, aby w widoku DisplayForModel była wyświetlana właściwość StateName, a widok EditorForModel używał właściwości (na tej podstawie renderuję listę rozwijaną).

Nie byłem w stanie dowiedzieć się, jak ozdobić moje właściwości viewmodelu, aby stworzyć takie zachowanie.

Odpowiedz

14

Chciałem rozwiązanie, które było bardziej uniwersalne, a więc stworzyłem nowy atrybut :

[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 
} 

i obejmowały następujący kod w moim niestandardowego DataAnnotationsModelMetadataProvider:

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; 
    } 
} 

tak, że mogę po prostu ozdobić mój model jako tak:

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

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

Jak wdrożyć zwyczaj DataAnnotationsModelMetadataProvider? Dzięki. – UpTheCreek

+0

@UpTheCreek - Dziedzicz z 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

Dziękujemy za udostępnienie rozwiązanie. Byłoby jednak przydatne, gdybyś mógł podać szczegóły dotyczące miejsca, w którym musi się znaleźć drugi fragment kodu (zakładam, że musimy przesłonić CreateMetadata i umieścić go tam?), A także jak zarejestrować nasz niestandardowy DataAnnotationsModelMetadataProvider po utworzeniu. – mutex

0

Przestawianie szablony:

W ~/Shared/EditorTemplates/DepartmentViewModel.ascx put:

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

iw swoim ~/Shared/DisplayTemplates/DepartmentViewModel.ascx:

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

Oto mój dostawca zwyczaju, ja dodać Żaden tryb

renderowanie
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

Komentarz na temat odpowiedzi CodeGrue.

Atrybut ten będzie dziedziczyć zamiast IMetadataAware. W ten sposób nie trzeba budować własnego DataAnnotationsModelMetadataProvider.

Nowy atrybut stałoby się coś takiego:

[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 
} 
Powiązane problemy