如何在 ASP.NET MVC 中使用复选框创建选择列表?

9

我有一个数据库表记录用户可以访问哪些出版物。这个表非常简单 - 它只存储用户ID/出版物ID对:

CREATE TABLE UserPublication (UserId INTEGER, PublicationID INTEGER)

对于给定用户和出版物,存在记录意味着该用户具有访问权限;缺少记录意味着没有访问权限。
我希望向管理员用户展示一个简单的屏幕,允许他们配置用户可以访问哪些出版物。我想为每个可能的出版物显示一个复选框,并检查用户当前可以访问的那些出版物。管理员用户随后可以选择或取消选择任意数量的出版物并提交表单。
有各种类型的出版物,我想将类似类型的出版物分组在一起 - 所以我确实需要控制如何呈现出版物(我不想只有一个平面列表)。
我的视图模型显然需要列出所有出版物的清单(因为我需要显示它们所有,无论当前选择如何),并且我还需要列出用户当前可以访问的出版物的清单。(我不确定是否最好使用单个列表,其中每个项目都包括出版物ID和一个是/否字段?)
但这就是我已经完成的工作了。我真的不知道如何将其绑定到一些复选框上。我从哪里开始?
1个回答

19

您的问题的 Linq to SQL 模型 大致如下所示:

alt text

首先,我们需要一些在我们的数据模型中使用的帮助对象

namespace SelectProject.Models
{
    public class UserPublicationSelector
    {
        public int UserPublicationID { get; set; }
        public int UserID { get; set; }
        public int PublicationID { get; set; }
        public string PublicationName { get; set; }
        public bool IsSelected { get; set; }
    }

    public class UserPublicationSelectViewModel
    {
        public User User { get; set; }
        public IQueryable Selections { get; set; }
    }
}

现在让我们创建一个看起来像这样的仓库

public class Repository
{
    DataContext dc = new DataContext();

    public User GetUser(int userID)
    {
        return dc.Users.FirstOrDefault(u => u.UserID == userID);
    }

    public IQueryable GetUserPublications(int userID)
    {
        return from p in dc.Publications
               join up in dc.UserPublications on p.PublicationID equals up.PublicationID
               where up.UserID == userID
               orderby p.PublicationName
               select p;
    }
    public IQueryable GetUserPublicationSelectors(int userID)
    {
        return from p in dc.Publications
               join up in dc.UserPublications on p.PublicationID equals up.PublicationID into selected
               from s in selected.DefaultIfEmpty()
               orderby p.PublicationName
               select new UserPublicationSelector
               {
                   UserPublicationID = (int?)s.UserPublicationID ?? 0,
                   UserID = userID,
                   PublicationID = p.PublicationID,
                   PublicationName = p.PublicationName,
                   IsSelected = s.UserID != null
               };
    }

    public void UpdateUserPublications(UserPublicationSelector[] selections)
    {
        // Insert records for new selections...
        foreach (UserPublicationSelector selection in selections.Where(s => s.IsSelected == true))
        {
            // ...where records do not yet exist in database.
            if (selection.UserPublicationID == 0)
            {
                UserPublication up = new UserPublication
                {
                    UserID = selection.UserID,
                    PublicationID = selection.PublicationID,
                };
                dc.UserPublications.InsertOnSubmit(up);
            }
        }
        // Delete records for unselected items...
        foreach (UserPublicationSelector selection in selections.Where(s => s.IsSelected == false))
        {
            // ...where record exists in database.
            if (selection.UserPublicationID > 0)
            {
                UserPublication up = dc.UserPublications.FirstOrDefault(s => s.UserPublicationID == selection.UserPublicationID);
                if (up.UserID == selection.UserID && up.PublicationID == selection.PublicationID)
                    dc.UserPublications.DeleteOnSubmit(up);
            }
        }
        // Update the database
        dc.SubmitChanges();
    }
}

还需要一个看起来像这样的控制器

public class PublicationController : Controller
{
    Repository repository = new Repository();

    public ActionResult Index(int id)
    {
        User user = repository.GetUser(id);
        var publications = repository.GetUserPublications(id);
        ViewData["UserName"] = user.UserName;
        ViewData["UserID"] = user.UserID;
        return View("Index", publications);
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Select(int id)
    {
        var viewModel = new UserPublicationSelectViewModel()
        {
            User = repository.GetUser(id),
            Selections = repository.GetUserPublicationSelectors(id)
        };
        return View("Select", viewModel);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Select(int userID, UserPublicationSelector[] selections)
    {
        repository.UpdateUserPublications(selections);
        return RedirectToAction("Index", new { id = userID });
    }
}

索引视图如下所示:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Publication>>" %>
<%@ Import Namespace="SelectProject.Models" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    List of Selected Publications for User
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Publications for <%= ViewData["UserName"] %></h2>

        <table id="MyTable" style="width: 100%">
            <thead>
                <tr>
                    <th>
                        Publication Name
                    </th>
                </tr>
            </thead>

            <tbody>
                <%  int i = 0;
                    foreach (Publication item in Model)
                    { %>

                    <tr id="row<%= i.ToString() %>">
                        <td>
                            <%= Html.Encode(item.PublicationName)%>
                        </td>
                    </tr>

                    <% i++;
                    } %>
            </tbody>
        </table>
        <p>
            <%= Html.ActionLink("Edit Selections", "Select", new { id = ViewData["UserID"] })%>
        </p> 

</asp:Content>

选择视图 看起来像这样:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<UserPublicationSelectViewModel>" %>
<%@ Import Namespace="SelectProject.Models" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Select Publications
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Select Publications for <%= Model.User.UserName %></h2>

    <% using (Html.BeginForm())
       { %>

        <table id="MyTable" style="width: 100%">
            <thead>
                <tr>
                    <th style="width: 50px; text-align:center">
                        <input type="checkbox" id="SelectAll" />
                    </th>
                    <th>
                        Publication Name
                    </th>
                </tr>
            </thead>

            <tbody>
                <%  int i = 0;
                    foreach (UserPublicationSelector item in Model.Selections)
                    { %>

                    <tr id="row<%= i.ToString() %>">
                        <td align="center" style="padding: 0 0 0 0">
                            <%= Html.CheckBox("selections[" + i.ToString() + "].IsSelected", item.IsSelected)%>
                            <%= Html.Hidden("selections[" + i.ToString() + "].UserPublicationID", item.UserPublicationID)%>
                            <%= Html.Hidden("selections[" + i.ToString() + "].UserID", Model.User.UserID)%>
                            <%= Html.Hidden("selections[" + i.ToString() + "].PublicationID", item.PublicationID)%>
                        </td>
                        <td>
                            <%= Html.Encode(item.PublicationName)%>
                        </td>
                    </tr>

                    <% i++;
                    } %>
            </tbody>
        </table>
        <p>
            <%= Html.Hidden("userID", Model.User.UserID) %>
            <input type="submit" value="save" />
        </p> 

    <% } // End Form %>

    <script src="../../Scripts/jquery-1.4.1.js" type="text/javascript"></script>

    <script type="text/javascript">
        // Select All Checkboxes
        $(document).ready(function() {
            $('#SelectAll').click(function() {
                var newValue = this.checked;
                $('input:checkbox').not('input:hidden').each(function() {
                    this.checked = newValue;
                });
            });
        });
    </script>

</asp:Content>

以下是一些屏幕截图。

alt text

alt text

左上角的复选框是一个全选/取消全选复选框。


太棒了,谢谢。我感觉有点不好意思,就像是我付钱让你帮我做作业一样 :-) - Gary McGill
1
@TonyP:该功能位于Select视图中,使用“AcceptVerbs HttpVerbs.Post”属性值的“Select”控制器方法中,并在上面演示了UpdateUserPublications存储库方法。 - Robert Harvey
在你的 GetUserPublicationSelectors(int userID) 函数中,IsSelected = s.UserId != null 将始终为真。这是正确的吗? - Shawn Mclean
你好 @robert 非常好的答案! 我在使用MVC3时卡在了edit.cshtml中<code> 找不到类型或命名空间名称“PostCategorySelector”(您是否缺少using指令或程序集引用?) </code> - user615700
@colorblack04:我在谷歌搜索中没有看到那个名字,它一定是你的程序特有的东西。 - Robert Harvey
显示剩余2条评论

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