MVC 和实体框架 Html.DisplayNameFor 与复合 ViewModel [英] MVC and Entity Framework Html.DisplayNameFor with Composite ViewModel

查看:27
本文介绍了MVC 和实体框架 Html.DisplayNameFor 与复合 ViewModel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对使用 WPF/Silverlight 的 MVVM 相当满意,但这是我第一次尝试 MVC Web 应用程序……只是我的背景仅供参考.

I’m fairly comfortable with MVVM using WPF/Silverlight but this is my first attempt at an MVC Web Application…just an fyi for my background.

我创建了一个名为 TestSitesController 的控制器,它是从我的实体框架模型(生成读/写操作和视图的模板)中的站点"模型类自动生成的.我唯一修改的是在 3 个地方,某些方法有一个 Guid id = null 的默认参数.我刚刚摆脱了= null",一切正常.这是我更改的示例

I’ve created a controller called TestSitesController which was auto generated from from the "Site" model class in my Entity Framework Model (the template that generates the read/write actions and views). The only thing I modified was in 3 spots there was a default parameter of Guid id = null for some methods. I just got rid of the " = null" all works fine. Here is an example of what I changed

public ActionResult Delete(Guid id = null)
{
    //....
}

这里改成

public ActionResult Delete(Guid id)
{
    //....
}

Site 模型没有什么特别之处,SiteId、Abbreviation 和 DisplayName……对于这个问题,我们试图让它尽可能简单.好的,所以我运行网站并转到 htpp://.../TestSites/一切正常.

The Site model is nothing special SiteId, Abbreviation, and DisplayName…trying to keep it as simple as possible for this question. Ok so I run the website and goto htpp://.../TestSites/ and everything works perfectly.

我注意到我的所有视图(创建、删除、详细信息和编辑)都使用了 @model MVCWeb.MyEntities.Site,我现在完全可以接受;但在 Index.cshtml 视图中,我注意到它使用了

I noticed that all of my views (Create, Delete, Details and Edit) are using an @model MVCWeb.MyEntities.Site which I’m perfectly ok with for now; but in the Index.cshtml view I noticed it was using an

@model IEnumerable<MVCWeb.MyEntities.Site>

这适用于生成的模板,但我想使用复合视图模型",也许这就是我试图混合我的 MVVM 知识的地方,但如果可能的话,我会坚持下去.在我看来,复合视图模型只是一个特定于由 1 个或多个实体模型以及 SelectedSiteId 等附加属性组成的视图的模型.

This works fine for the generated template but I would like to use a "Composite View Model" and maybe this is where I’m trying to mix in my MVVM knowledge but would to stick with that if all possible. In my mind a Composite View Model is just a Model that is specific towards a view that is composed of 1 or more Entity Models along with additional properties like SelectedSiteId, etc.

所以我创建了一个非常简单的 ViewModel,叫做 TestSitesViewModel

So I created a very simple ViewModel called TestSitesViewModel

public class TestSitesViewModel
{
    //Eventually this will be added to a base ViewModel to get rid
    //of the ViewBag dependencies
    [Display(Name = "Web Page Title")]
    public string WebPageTitle;

    public IEnumerable<MVCWeb.MyEntities.Site> Sites;

    //Other Entities, IEnumberables, or properties go here
    //Not important for this example
}

然后在我的控制器中我添加了一个名为 IndexWithViewModel 的操作方法

Then in my controller I added an action method called IndexWithViewModel

public ActionResult IndexWithViewModel()
{
    var vm = new TestSitesViewModel();
    vm.WebPageTitle = "Sites With Composite View Model";
    vm.Sites = db.Sites.ToList();

    return View(vm);
}

然后我复制了 Index.cshtml 并将其命名为 IndexWithModel.cshtml 以匹配我的新 ActionResult 方法名称.我改变了

I then made a copy of the Index.cshtml and named it IndexWithModel.cshtml to match my new ActionResult method name. I changed the top line of

@model IEnumerable<MVCWeb.MyEntities.Site>

@model MVCWeb.Models.TestSitesViewModel

我在表格部分之前添加了这个来测试 DisplayNameFor 和 DisplayFor

I added this before the table section to test for the DisplayNameFor and the DisplayFor

@Html.DisplayNameFor(model => model.WebPageTitle)
&nbsp;
@Html.DisplayFor(model => model.WebPageTitle)
<br />

改变了

@foreach (var item in Model) {

@foreach (var item in Model.Sites) {

并暂时注释掉包含所有表头的 tr 部分.一切正常,除了@Html.DisplayNameFor 显示WebPageTitle"的变量名而不是使用网页标题",如

And commented out the tr section that contains all of the table headers for now. Everything works perfectly except that the @Html.DisplayNameFor is displaying the variable name of "WebPageTitle" instead of using "Web Page Title" as denoted in the Display attribute of the Data Annotation in

[Display(Name = "Web Page Title")]
public string WebPageTitle;

此外,如果我在包含表头信息的 tr 部分进行评论.我终其一生都无法弄清楚该放什么我已经尝试过 model.Sites.Abbreviation、model.Sites[0].Abbreviation 和其他各种组合,但都出现错误.

Also if I comment back in the tr section that contains the table header information. I can not for the life of me figure out what to put in I’ve tried model.Sites.Abbreviation, model.Sites[0].Abbreviation, and various other combinations but get errors.

<tr>
    <th>
        @Html.DisplayNameFor(model => model.Abbreviation)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.DisplayName)
    </th>
    <th></th>
</tr>

那我应该在那里使用什么?我不太确定为什么 model.Sites.Abbreviation 不起作用,因为 Sites 与原始 Index.cshtml 中用作模型的类型完全相同

So what should I use there? I'm not quite sure why model.Sites.Abbreviation doesn't work as Sites is the exact same type that was used as the model in the original Index.cshtml

推荐答案

我折腾了几个小时终于搞明白了.

I finally figured this out after messing around for several hours.

第一个问题,为了在数据注释中使用显示属性,必须添加 get 和 set acessor 方法,即使它们只是默认方法.我假设这是因为它们只能对属性起作用,而不能对类的公共数据成员起作用.这是获取

1st problem in order to use the Display arrtibute in the Data Anotations a get and set acessor methods must be added even if they are only the default ones. I'm assuming this is because they must only work on properties and not public data members of a class. Here is code to get the

@Html.DisplayNameFor(model => model.WebPageTitle)

正常工作

public class TestSitesViewModel
{
    //Eventually this will be added to a base ViewModel to get rid of
    //the ViewBag dependencies
    [Display(Name = "Web Page Title")]
    public string WebPageTitle { get; set; }

    //PUBLIC DATA MEMBER WON'T WORK
    //IT NEEDS TO BE PROPERTY AS DECLARED ABOVE
    //public string WebPageTitle;

    public IEnumerable<MVCWeb.MyEntities.Site> Sites;

    //Other Entities, IEnumberables, or properties go here
    //Not important for this example
}

问题的第二部分是访问 IEnumerable 变量中的元数据.我声明了名为 headerMetadata 的临时变量并使用它而不是尝试通过 IEnumerable 访问属性

2nd part of problem was accessing the Metadata in an IEnumerable variable. I declared temporary variable called headerMetadata and used it instead of trying to access the properties through the IEnumerable

@{var headerMetadata = Model.Sites.FirstOrDefault();}
<tr>
    <th>            
        @Html.DisplayNameFor(model => headerMetadata.Abbreviation)
    </th>
    <th>
        @Html.DisplayNameFor(model => headerMetadata.DisplayName)
    </th>
    ...

这确实引出了 headerMetadata 变量何时超出范围的问题?它适用于整个视图还是仅限于 html table 标签?我想这是另一个约会的另一个问题.

This does beg the question of when does headerMetadata variable go out of scope? Is it available for the entire view or is it limited to the html table tags? I suppose that's another question for another date.

这篇关于MVC 和实体框架 Html.DisplayNameFor 与复合 ViewModel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆