Отображение различных полей в режиме EditorForModel и DisplayForModel в MVC2 - PullRequest
10 голосов
/ 02 июня 2010

У меня есть модель просмотра, которая имеет поле int StateID и поле string StateName, например:

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 используется свойство StateID (на самом деле я отображаю раскрывающийся список на основе этого).

Я не смог выяснить, как украсить свои свойства viewmodel, чтобы создать такое поведение.

Ответы [ 4 ]

17 голосов
/ 06 декабря 2011

Комментарий к ответу 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
}
14 голосов
/ 02 июня 2010

Мне нужно более общее решение, поэтому я создал новый атрибут:

[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; }     
} 
1 голос
/ 02 марта 2011

Вот мой пользовательский провайдер, я добавляю режим рендеринга Нет

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;
    }
}
0 голосов
/ 02 июня 2010

Переопределить шаблоны:

В ~/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>
...