当Views根据条件需要不同的ViewModel时,如何建模ViewModel?

时间:2011-08-21 19:34:16

标签: asp.net-mvc asp.net-mvc-3

我正在建立一个问号。它一次显示两个问题。问题可以是不同类型的。例如,多选问题和“矩阵”问题,其中有许多行和列需要回答。

我目前没有使用ViewModels,只是实体模型(我知道我不应该这样做)..

检索问题列表的代码:

        public ActionResult QuestionList(int categoryId, int page)
    {
        var questions = new PagedData<Question>();

        questions.Data = db.Question.Where(c => c.category_id == categoryId).OrderBy(p => p.question_number).Skip(PageSize * (page - 1)).Take(PageSize).ToList();
        questions.NumberOfPages = Convert.ToInt32(Math.Ceiling((double)db.Question.Where(cc => cc.category_id == categoryId).Count() / PageSize));
        questions.CurrentPage = page;
        questions.CategoryID = categoryId;

        return PartialView("QuestionList", questions);
    }

View看起来像这样:

    @model MvcApplication3.Helpers.Paging.PagedData<MvcApplication3.Models.Question>


@if (Model.Data.Count() == 0)
{
<h2>Denne kategori har ingen spørgsmål</h2>
}
else
{
    <h2>@Model.Data.First().Category.category_name</h2>

    <br />

    <div>

    Tryk for at komme videre til side: 

    @for (int i = 1; i <= Model.NumberOfPages; i++)
    {
        if (i == Model.CurrentPage)
        {
            @i
        }
        else
        {
            <a class="page-number" href="javascript:void();">@i</a>
        }
    }
    </div>
    <br />

    foreach (var item in Model.Data)
    {
        if (item.visible == true)
        {
            String isAnswered = null;
            if (item.Tabelform_Answers.Count() >= 1)
            {
                isAnswered = "answered";
            }
            else if(item.MCQ_Answers.Count() >= 1) 
            {
                isAnswered = "answered";
            }
            else
            {
                isAnswered = "unanswered";
            }

            <div id=@isAnswered>

            @if (User.IsInRole("Administrator"))
            {
                @Html.ActionLink("[Rediger]", "Edit", "AdminQuestion", new { id = item.question_id }, null)    
            }

            @Html.LabelFor(y => item.question_wording, item.question_wording, new { @class = "tooltip", title = @item.help_text })

            @if (item.Question_Type.type_description == "Multiple Choice")
            {
                <br />
                @Html.Partial("MCQDisplay", item)
            }
            else if (item.Question_Type.type_description == "Tabelform")
            {
                <br /><br />
                @Html.Partial("GridDisplay", item)
            }

            </div>
            <br />   
        }
    }

}

@Html.HiddenFor(m => m.NumberOfPages)
@Html.HiddenFor(m => m.CategoryID)
@Html.HiddenFor(m => m.CurrentPage)

我不想将整个Question实体发送到部分视图MCQDisplay和GridDisplay,而是仅发送数据neccecary。

这个ViewModel应该如何?

我的想法是在主ViewModel中为每种类型的问题提供一个列表,如下所示:

List<MultipleChoiceViewModel> mcqlist;
List<GridQuestionViewModel> gridlist;

如果类别中没有“多项选择”类型的问题,则列表将为空并且不会被使用。这是好习惯吗?

1 个答案:

答案 0 :(得分:1)

你可以试试的是这个。我不是100%肯定它会工作,因为我不知道MVC框架是否只会寻找模型类型,或者它是真正的类型。

传递base clas作为模型类型,然后从基类类型派生不同的viewmodel。然后为每种问题类型定义编辑器模板,只需对该类型使用DisplayFor或EditorFor,然后让它自行渲染。

正如我所说,这将取决于MVC是否使用它的最终类型,或仅仅​​是基本类型。

编辑:

您创建了一个名为QuestionViewModel的基类,它不需要任何属性或方法,但是如果有常用的方法或属性,可以将它们放在这里。

然后从MultipleChoiceViewModel派生GridQuestionViewModelQuestionViewModel

在您的视图中:

@model IEnumerable<QuestionViewModel>

@Html.EditorForModel()

然后在Views / Whatever文件夹中为每种类型在Views / Shared文件夹中创建一个名为EditorTemplates的文件夹,然后为每种类型定义html。

MVC应该自动知道问题是GridQuestionViewModel,并在传递它们的列表时使用它的编辑器模板。