9

我刚刚开始学习 MVC4,我必须承认我对 lambda 表达式、泛型和匿名类型的所有依赖有点挑战,尤其是当有许多重载函数时。尝试理解 HTML Helpers 的工作原理有点令人困惑。以“DropDownListFor”Helper 为例。我试图从我的代码中提取要领。这就是为什么您在表格中只看到一个“性别”列。希望它在语法上仍然正确:

@model IEnumerable<BusinessLayer.Employee>
<table>
    @foreach (var employee in Model) 
    {    
        <tr>
            <td>
            @{

                var listItems = new List<SelectListItem>()
                {
                    new SelectListItem {Text = "Male",   Value = "M"},
                    new SelectListItem {Text = "Female", Value = "F"}
                };

                @Html.DropDownListFor(m => employee.Gender, listItems, listItems.Find(i => i.Value == employee.Gender).Text)                          
            }  

            </td>
        </tr>
    }
</table>        

Model对象中有两个Employees,一个Employee的IEnumerable,生成如下HTML

<table> 
    <tr>
        <td>
            <select id="employee_Gender" name="employee.Gender"><option value="">Male</option>
                <option value="M">Male</option>
                <option value="F">Female</option>
            </select>
    </tr>       
        </td>    
             <select id="employee_Gender" name="employee.Gender"><option value="">Female</option>
                <option value="M">Male</option>
                <option value="F">Female</option>
             </select>                
        </td>
</table>                

查看 DropDownListFor 方法的第一个参数,

@Html.DropDownListFor(m => employee.Gender, ...

...我是否正确理解“m”代表传递给视图的模型类的实例?在我看到的在线示例中,我看到了“m”似乎是指模型类但模型是单个实例类的示例,例如,单个 Employee 对象,而不是Employees 的集合在这种情况下,我想显示员工的表格列表。我假设 DropDownListFor 方法的第一个参数的意图是“指向/绑定”到一个属性在模型中,这就是我制作 m => employee.Gender 的原因。当模型是员工的集合而不是单个员工时,我应该这样做吗?如果是这样,我很困惑如何为两个下拉列表生成唯一 ID,这两个下拉列表都为 NAME 和 ID 属性分配了“employee_Gender”。

对于 Helper DropDownListFor 的第三个参数,

listItems.Find(i => i.Value == employee.Gender).Text

这合理吗?employee.Gender 的值为“M”或“F”,但显示文本为“Male”和“Female”。我很困惑这个参数是否用于指定默认的“NO SELECT”第一个值,或者这个参数是否用于从下拉列表中选择当前员工的值——或者它可能两者都做?例如,如果找到,它是否选择指定的文本,否则添加指定为FIRST 的文本?如果找不到该值的参数?从我所看到的情况来看,这似乎是它的工作方式。这第三个参数可以简化还是我的例子合理?

感谢您耐心阅读我的许多问题,以更好地理解这一点。

4

1 回答 1

25

第 1 部分:解释 Lambda 魔法

你不是一个人。Lambdas + MVC 使编码变得容易,但它们也使它看起来相当神奇(由于抽象)。

查看 DropDownListFor 方法的第一个参数 [...] 我是否正确理解“m”表示传递给视图的模型类的实例?

是的。

Razor 中的 HTML Helpers + Lambdas 既简单又神奇,因为它们走的是捷径,实际上并没有向您揭示发生了什么。

首先,我们来看看@Html。我们知道@开始我们的 Razor 语法,然后Html是魔法。实际上,Html是一个自动初始化并提供给您的HtmlHelper对象。更具体地说,它是一个HtmlHelper<TModel>. Razor HTML 编辑器很智能,可以根据您所说的视图模型类型提前知道 TModel 将是什么类型。这就是为什么你有这么多智能。

当您键入

@model IEnumerable<BusinessLayer.Employee>

编辑器读取了它并假设 HTML Helper 将是HtmlHelper<IEnumerable<BusinessLayer.Employee>>. 当需要编译页面时,HTML 助手实际上就是那种类型(当然)。

那么,DropDownListFor或者任何其他扩展方法呢?

查看DropDownListFor我们可以看到它实际上是DropDownListFor<TModel, TProperty>. 我们现在明白 TModel 是我们视图的模型类型。DropDownListFor知道这一点,因为该方法正在扩展 HtmlHelper<TModel>。因此 DropDownListFor 知道传入的类型是视图顶部定义的任何类型。怎么样TProperty

TProperty是返回类型。这是您在选择属性时指定的类型。视图为 HtmlHelper 提供模型类型,然后由模型类型提供 DropDownListFor ,现在您处于 lambda 表达式中:(x => x.Property)您选择属性,然后为您选择类型;在本例中为字符串(性别)。

第 2 部分:您的问题

如果不确切知道您要达到的目标,就很难回答您的问题。您是否有一组员工,并且您想为每个员工显示多个性别下拉框,然后保存它们?

在处理集合时,它有点棘手,因为 MVC 不能开箱即用地处理它们;通常最好根据您的需要编写自己的解决方案。

我真的不喜欢单个视图在页面上获取事物集合的想法。考虑这个逻辑:

你的方式:

  • 获取员工集合
  • 给员工一个视图
  • 让视图创建一个 SelectListItem
  • 循环并显示每个员工的 SelectList

我的方式

  • 获取员工集合
  • 让员工看到
  • 让视图循环并将每个员工传递到另一个视图(部分)
  • 每个部分处理一个员工

使用 MVC 确实尝试将事物分解为小的、符合逻辑的部分。观点应该是愚蠢的;这意味着他们不应该真正做任何逻辑或思考。通过这种方式,事情变得更容易,它可以确保你的观点不会变成怪物。

示例解决方案演练

试试这个:

在与您正在使用的视图相同的文件夹中创建一个名为 _EmployeeGender.cshtml 的新 PartialView

使用此代码

_EmployeeGender.cshtml

@model BusinessLayer.Employee

<tr>
    <td>
    @{

        var listItems = new List<SelectListItem>()
        {
            new SelectListItem {Text = "Male",   Value = "M"},
            new SelectListItem {Text = "Female", Value = "F"}
        };

        @Html.DropDownListFor(m => m.Gender, listItems, string.Empty)
    }  

    </td>
</tr>

你原来的看法

@model IEnumerable<BusinessLayer.Employee>
@{
    ViewBag.Title = "Employees";
}

<h2>Employees</h2>

<table>
    @foreach (var employee in Model) 
    {
        Html.RenderPartial("_EmployeeGender", employee);
    }
</table>

结果

现在让我们看看我们生成的 HTML

<table>
<tr>
    <td>
<select id="Gender" name="Gender"><option value=""></option>
<option selected="selected" value="M">Male</option>
<option value="F">Female</option>
</select>  

    </td>
</tr><tr>
    <td>
<select id="Gender" name="Gender"><option value=""></option>
<option value="M">Male</option>
<option selected="selected" value="F">Female</option>
</select>  

    </td>
</tr></table>

我们可以看到现在有一​​个空白选择,并且我们的下拉框自动选择了员工的值(我创建了一名男性和一名女性员工)。

请注意idnameHTML 属性是相同的。如果您想提交具有这些值的表单,则需要更多的工作。但这对您来说是一个合理的起点。

于 2013-11-01T04:27:52.213 回答