2010-06-02 24 views
10

我有了一個int StateID領域,像這樣一個string StateName領域的視圖模型:顯示在EditorForModel不同領域與DisplayForModel模式在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; } 
} 

我有一個使用DisplayForModel只讀視圖和更新視圖使用EditorForModel。我希望DisplayForModel視圖顯示StateName屬性,EditorForModel視圖使用​​屬性(我實際上正在渲染基於此的下拉列表)。

我一直無法弄清楚如何裝飾我的viewmodel屬性來創建此行爲。

回答

14

我想一個解決方案,更通用的,所以我創建了一個新的屬性:

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

並列入我的自定義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; 
    } 
} 

所以,我可能只是裝點我的模型像這樣:

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

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

如何實現自定義DataAnnotationsModelMetadataProvider?謝謝。 – UpTheCreek 2010-08-04 12:57:00

+0

@UpTheCreek - 從DataAnnotationsModelMetadataProvider繼承。 http://weblogs.asp.net/seanmcalinden/archive/2010/06/11/custom-asp-net-mvc-2-modelmetadataprovider-for-using-custom-view-model-attributes.aspx – CodeGrue 2010-08-04 13:02:59

+2

感謝您分享您的解。如果你可以詳細說明第二個代碼段需要去哪裏(我假設我們需要重寫CreateMetadata並將其放在那裏?)以及一旦創建後如何註冊我們的自定義DataAnnotationsModelMetadataProvider,這將是有用的。 – mutex 2011-02-06 21:48:59

0

重寫模板:

~/Shared/EditorTemplates/DepartmentViewModel.ascx地說:

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

而在你~/Shared/DisplayTemplates/DepartmentViewModel.ascx

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

這裏是我的自定義提供商,我添加了一個無渲染模式

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

對CodeGrue的回答發表評論。

改爲使屬性繼承IMetadataAware。這樣你就不需要建立你自己的DataAnnotationsModelMetadataProvider。

新的屬性將成爲類似:

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