2010-06-02 8 views
10

Ich habe ein Ansichtsmodell, das wie so ein int StateID Feld und ein string StateName Feld hat:zeigen verschiedene Felder in EditorForModel vs. DisplayForModel Modi in 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; } 
} 

Ich habe eine Nur-Lese-Ansicht, die DisplayForModel und Update-Ansicht verwendet das verwendet EditorForModel. Ich möchte, dass die DisplayForModel Ansicht die StateName Eigenschaft zeigt, und die EditorForModel Ansicht die StateID Eigenschaft verwenden (ich rendere tatsächlich eine Dropdownliste basierend auf dieser).

Ich konnte nicht herausfinden, wie meine Viewmodel-Eigenschaften zu dekorieren, um dieses Verhalten zu erstellen.

Antwort

14

ich wollten eine Lösung, die allgemeinere war, so habe ich ein neues Attribut :

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

Und den folgenden Code in meiner benutzerdefinierten DataAnnotationsModelMetadataProvider enthalten:

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

Damit ich genauso so mein Modell schmücken konnte:

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

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

Wie setzen Sie das benutzerdefinierte DataAnnotationsModelMetadataProvider? Vielen Dank. – UpTheCreek

+0

@UpTheCreek - Vererbt von 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

Danke für die Freigabe Ihrer Lösung. Es wäre jedoch nützlich, wenn Sie Details darüber angeben könnten, wohin das zweite Code-Snippet gehen soll (ich nehme an, wir müssen CreateMetadata überschreiben und dort einfügen?) Und auch, wie wir unseren benutzerdefinierten DataAnnotationsModelMetadataProvider registrieren, sobald er erstellt wurde. – mutex

0

die Vorlagen außer Kraft setzen:

In ~/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) %> 

Und in Ihrem ~/Shared/DisplayTemplates/DepartmentViewModel.ascx:

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

Hier ist meine benutzerdefinierten Anbieter, füge ich ein Render-Modus Keine

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

Ein Kommentar zu CodeGrues Antwort.

Lassen Sie das Attribut stattdessen IMetadataAware erben. Auf diese Weise müssen Sie nicht Ihren eigenen DataAnnotationsModelMetadataProvider erstellen.

würde das neue Attribut wird so etwas wie:

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