简体   繁体   English

具有复合ViewModel的MVC和实体框架Html.DisplayNameFor

[英]MVC and Entity Framework Html.DisplayNameFor with Composite ViewModel

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. 我对使用WPF / Silverlight的MVVM非常熟悉,但这是我第一次尝试使用MVC Web应用程序...这只是我的背景。

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). 我创建了一个名为TestSitesController的控制器,它是从我的实体框架模型中的“站点”模型类(生成读/写操作和视图的模板)中自动生成的。 The only thing I modified was in 3 spots there was a default parameter of Guid id = null for some methods. 我修改的唯一的东西是3个点,对于某些方法,有一个默认参数Guid id = null。 I just got rid of the “ = null” all works fine. 我只是摆脱了“= null”一切正常。 Here is an example of what I changed 这是我改变的一个例子

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

This was changed to 这被改为

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

The Site model is nothing special SiteId, Abbreviation, and DisplayName…trying to keep it as simple as possible for this question. Site模型没有什么特别的SiteId,Abbreviation和DisplayName ...试图让这个问题尽可能简单。 Ok so I run the website and goto htpp://.../TestSites/ and everything works perfectly. 好的,所以我运行网站并转到htpp://.../TestSites/,一切都很完美。

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; 我注意到我的所有视图(创建,删除,详细信息和编辑)都使用@model MVCWeb.MyEntities.Site,我现在完全可以使用它; but in the Index.cshtml view I noticed it was using an 但在Index.cshtml视图中,我注意到它正在使用

@model IEnumerable<MVCWeb.MyEntities.Site>

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. 这适用于生成的模板,但我想使用“复合视图模型”,也许这就是我试图混合我的MVVM知识,但如果可能的话就会坚持下去。 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. 在我看来,复合视图模型只是一个特定于一个视图的模型,该视图由一个或多个实体模型以及像SelectedSiteId等其他属性组成。

So I created a very simple ViewModel called TestSitesViewModel 所以我创建了一个非常简单的ViewModel,名为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
}

Then in my controller I added an action method called IndexWithViewModel 然后在我的控制器中添加了一个名为IndexWithViewModel的动作方法

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

    return View(vm);
}

I then made a copy of the Index.cshtml and named it IndexWithModel.cshtml to match my new ActionResult method name. 然后我制作了一份Index.cshtml副本并将其命名为IndexWithModel.cshtml以匹配我的新ActionResult方法名称。 I changed the top line of 我改变了顶线

@model IEnumerable<MVCWeb.MyEntities.Site>

To

@model MVCWeb.Models.TestSitesViewModel

I added this before the table section to test for the DisplayNameFor and the DisplayFor 我在表部分之前添加了这个来测试DisplayNameFor和DisplayFor

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

Changed the 改变了

@foreach (var item in Model) {

To

@foreach (var item in Model.Sites) {

And commented out the tr section that contains all of the table headers for now. 并注释掉了包含所有表头的tr部分。 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 除了@ Html.DisplayNameFor显示变量名称“WebPageTitle”而不是使用“Web页面标题”(如数据注释的Display属性中所示)之外,一切都运行良好。

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

Also if I comment back in the tr section that contains the table header information. 此外,如果我在包含表头信息的tr部分中回复。 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. 我不能为我的生活弄清楚放入什么我已经尝试过model.Sites.Abbreviation,model.Sites [0]。缩写,以及各种其他组合但是得到错误。

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

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 我不太清楚为什么model.Sites.Abbreviation不起作用,因为Sites是与原始Index.cshtml中的模型完全相同的类型

I finally figured this out after messing around for several hours. 经过几个小时的捣乱,我终于弄明白了。

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. 第一个问题是,为了在Data Anotations中使用Display arrtibute,必须添加get和set acessor方法,即使它们只是默认方法。 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)

to work correctly 工作正常

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
}

2nd part of problem was accessing the Metadata in an IEnumerable variable. 第二部分问题是在IEnumerable变量中访问元数据。 I declared temporary variable called headerMetadata and used it instead of trying to access the properties through the IEnumerable 我声明了名为headerMetadata的临时变量,并使用它而不是尝试通过IEnumerable访问属性

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

This does beg the question of when does headerMetadata variable go out of scope? 这确实提出了headerMetadata变量何时超出范围的问题? Is it available for the entire view or is it limited to the html table tags? 它可用于整个视图还是仅限于html表标签? I suppose that's another question for another date. 我想这是另一个日期的另一个问题。

I'll take a stab with my newly learned MVVM ASP.NET MVC experience. 我将学习新学到的MVVM ASP.NET MVC经验。

Instead of calling @Html.DisplayNameFor(model => model.WebPageTitle) , try using @Html.DisplayFor(model => model.WebPageTitle) . 而不是调用@Html.DisplayNameFor(model => model.WebPageTitle) ,尝试使用@Html.DisplayFor(model => model.WebPageTitle) You appear to be setting the WebPageTitle value in your IndexWithViewModel controller which should show up in your view. 您似乎在IndexWithViewModel控制器中设置WebPageTitle值,该值应显示在您的视图中。

Look into shared templates for ASP.NET MVC. 查看ASP.NET MVC的共享模板 You can set up custom templates or partials for DisplayFor/EditorFor helpers at /Views/Shared/EditorTemplates/Site.cshtml and /Views/Shared/DisplayTemplates/Site.cshtml . 您可以在/Views/Shared/EditorTemplates/Site.cshtml/Views/Shared/DisplayTemplates/Site.cshtml为DisplayFor / EditorFor帮助程序设置自定义模板或部分。 ASP.NET MVC will automatically pick up on those templates when rendering your Site object with DisplayFor and EditorFor. 在使用DisplayFor和EditorFor呈现Site对象时,ASP.NET MVC将自动获取这些模板。

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM