如何在没有 ViewData(强类型视图)的情况下绑定 Html.DropDownList

3

我似乎找不到一篇好的博客文章,展示如何在不使用"ViewData"魔术字符串的情况下将模型绑定到视图(使用强类型视图是我要尝试的方法)。

有人知道我需要在下面的内容中修改什么,直接将其绑定到我的模型吗?

视图

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of MvcApplication1.Category))" %>
<asp:Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server">
    <%=Html.DropDownList("CategoryList")%>
</asp:Content>

控制器

Function Index() As ActionResult
    Dim list As New List(Of Category)
    list.Add(New Category With {.CategoryID = 1, .CategoryName = "Test1"})
    list.Add(New Category With {.CategoryID = 2, .CategoryName = "Test2"})

    Return View()
End Function

编辑

以下是VB中的最终解决方案,感谢大家的热烈反应!

控制器

Function Index() As ActionResult
    Dim id As Integer = 1
    Dim ProductObject As Product = mProductService.GetProductById(id)

    Return View(ProductObject)
End Function

视图

<%=Html.DropDownList("Category", New SelectList(Model.Categories, "CategoryID", "CategoryName"))%>

产品类别(包含一个枚举属性用于分类)

Public Class Product
    Public Sub New()

    End Sub


    Private mProductID As Integer
    Public Property ProductID() As Integer
        Get
            Return mProductID
        End Get
        Set(ByVal value As Integer)
            mProductID = value
        End Set
    End Property

    ReadOnly Property Categories() As IEnumerable(Of Category)
        Get
            Dim list As New List(Of Category)
            list.Add(New Category With {.CategoryID = 1, .CategoryName = "Test1"})
            list.Add(New Category With {.CategoryID = 2, .CategoryName = "Test2"})

            Return list
        End Get
    End Property

End Class
3个回答

5
下拉列表助手需要一个IEnumerable<SelectListItem>而不是IEnumerable<Category>。通常情况下,您的页面拥有特定的模型。该模型包括下拉列表中选定值的属性,而不是集合。您通过ViewData提供要从中选择的集合。您可以拥有仅用于查看的模型,其中包括属性和要从中选择的集合,但这可能会导致类的增加。关于是否增加类或使用魔法字符串更糟糕的设计存在一些争议。
我的理解是您的代码应该像这样:
<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of Foo)" %>
<asp:Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server">
    <%=Html.DropDownList("Category", ViewData("CategoryList"))%>
</asp:Content>

Function Index() As ActionResult
    Dim list As New List(Of SelectListItem)
    list.Add(New SelectListItem  With {.Value = 1, .Text = "Test1"})
    list.Add(New SelectListItem With {.Value = 2, .Text = "Test2"})
    ViewData("CategoryList") = list
    Return View()
End Function

这里的Foo是一个包含int类型属性Category的类。

如果想要使用强类型视图,可以将Foo中的属性Category改为SelectListItem类型的属性Categories,然后进行如下更改:

<%=Html.DropDownList("Category", ViewData("CategoryList"))%>

to

<%=Html.DropDownList("Category", Foo.Categories )%>

并且

    ViewData("CategoryList") = list
    Return View()

为了

    Dim foo as New Foo
    foo.Categories = list
    Return View(foo)

1
我同意。这实际上就是我要做的,但我给出了直接的例子,以展示我认为他要求我们做的事情。好评论和示例文本。 - Adam Carr

1

您可以为 Html.DropDownList 创建自己的助手方法重载,直接将模型映射到 DropDownList 辅助程序。

话虽如此,你应该真正了解视图中应包含多少特定领域的逻辑。ViewData 可以帮助您将模型和领域逻辑与视图分离。

例如:

我知道这不是一个“重载”,因为我认为既然仍然需要一个名称,您会想要另一个方法,它只需使用字符串作为下拉列表的名称,但自动将模型绑定到控件(假设它是可枚举的)。这是 HtmlHelper 扩展方法的示例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MvcApplication3.Helpers
{
    public static class ViewHelpers
    {
        public static string ModelDropDownList(this HtmlHelper htmlHelper, string name)
        {
            var model = htmlHelper.ViewData.Model as IEnumerable<SelectListItem>;
            if(model == null)
                return string.Empty;

            return htmlHelper.DropDownList(name, model);
        }
    }
}

以下是如何在你的视图中调用它

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<SelectListItem>>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <%= Html.ModelDropDownList("Test") %>
</asp:Content>

好的,那我能否将ViewData("list")与模型混合使用呢?因为有时我需要填充一个表格/等等强类型视图,但我也需要填充一个下拉列表。我能在同一个视图中同时实现这两个功能吗? - Toran Billups
1
是的,因为这只会对您的API造成负担,但标准的方法签名仍将存在。 - Adam Carr
太好了!我可能会采用这种方法,因为我还没有编写自定义帮助器方法重载(虽然这是值得做的事情,因为我现在越来越少考虑WebForms)。 - Toran Billups
只是为了澄清我的关于ViewData的观点以及你对“将我的领域与视图分离”的评论 - 如果我真的需要这个,我会创建一个视图模型。这有助于消除浪费的LOC来执行左/右ViewData(“Name”)= object.Name,在我看来。 - Toran Billups
我的视图如何才能找到自定义帮助程序? - MetaGuru

0
如果您想采用强类型方法,可以使用SelectList对象,将其传递给IEnumerable。您需要指定T的文本字段和值字段属性,但是此SelectList对象可以直接分配给Html.DropDownList助手:
c#
IList<Category> categories = new IList<Category>()
    {
        new Category() { ID = 1, Name = "Category 1" },
        new Category { ID = 2, Name = "Category 2" }
    };

SelectList categoryDropDown = new SelectList(categories, "ID", "Name");

ViewData["categoryDropDown"] = categoryDropDown;

然后执行:

c#
<%=Html.DropDownList("CategoryID", ViewData("categoryDropDown"))%>

这样你就可以从任何地方(服务层、控制器宽方法)传递一个类别的 IList。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接