2010-06-02 24 views
10

Tôi có một viewmodel có một trường int StateID và một lĩnh vực string StateName như vậy:Hiển thị các lĩnh vực khác nhau trong EditorForModel vs chế độ DisplayForModel trong 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; } 
} 

Tôi có một chỉ đọc xem có sử dụng DisplayForModel và một cái nhìn cập nhật sử dụng EditorForModel. Tôi muốn chế độ xem DisplayForModel để hiển thị thuộc tính StateName và chế độ xem EditorForModel sử dụng thuộc tính StateID (Tôi thực sự đang hiển thị danh sách thả xuống dựa trên điều này).

Tôi chưa thể tìm ra cách trang trí các thuộc tính chế độ xem của mình để tạo hành vi này.

Trả lời

14

Tôi muốn có một giải pháp đó là chung chung hơn, vì vậy tôi đã tạo ra một thuộc tính mới :

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

Và bao gồm đoạn mã sau vào DataAnnotationsModelMetadataProvider tùy chỉnh của tôi:

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

Vì vậy mà tôi chỉ có thể trang trí mô hình của tôi như vậy:

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

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

Làm thế nào để bạn thực hiện các tùy chỉnh DataAnnotationsModelMetadataProvider? Cảm ơn. – UpTheCreek

+0

@UpTheCreek - Thừa kế từ 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

Cảm ơn bạn đã chia sẻ dung dịch. Nó sẽ hữu ích mặc dù nếu bạn có thể cung cấp chi tiết về nơi đoạn mã thứ hai cần phải đi (tôi giả sử chúng ta cần ghi đè lên CreateMetadata và đặt nó trong đó?) Và cũng làm thế nào để đăng ký DataAnnotationsModelMetadataProvider tùy chỉnh của chúng tôi khi được tạo. – mutex

0

Override các mẫu:

Trong ~/Shared/EditorTemplates/DepartmentViewModel.ascx đặt:

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

Và trong ~/Shared/DisplayTemplates/DepartmentViewModel.ascx của bạn:

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

Đây là nhà cung cấp tùy chỉnh của tôi, tôi thêm một None chế độ

làm
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

Nhận xét về câu trả lời của CodeGrue.

Làm cho thuộc tính kế thừa IMetadataAware thay thế. Bằng cách đó bạn không cần phải xây dựng DataAnnotationsModelMetadataProvider của riêng mình.

Thuộc tính mới sẽ trở thành cái gì đó như:

[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 
} 
Các vấn đề liên quan