【问题标题】:Creating a field for multiselect dropdown based on self (without creating a new model)基于自身创建多选下拉字段(不创建新模型)
【发布时间】:2018-08-29 19:02:47
【问题描述】:

我正在尝试为我的 BugTracker 实现多选下拉功能,但似乎找不到不涉及创建另一个模型的解决方案。以下是它的工作原理:

我有一个名为 Report 的模型,其中包含有关错误的信息。该模型包含诸如错误名称、紧急程度、提交日期、解决方案等字段。我想要的是添加一个实际上是相关错误列表的字段。因此,当程序员更新这个报告时,他可以从以前的错误(报告)列表中选择并添加多个报告编号。查看(未编辑)报告时,这些数字将显示为报告页面的 ActionLink。所以也许用户看到了这个:

相关错误:1、37、56

它背后的代码是这样的:

RelatedBugs: @Html.ActionLink("1", "Admin", "Report", 1, null), @Html.ActionLink("37", "Admin", "Report", 37, null), @ Html.ActionLink("56", "Admin", "Report", 56, null)

(这些数字实际上是下面的 Report.cs 的 ID。)

所以在表单的编辑视图中,会有一个多选下拉菜单,您可以在其中选择所有这些错误。这类似于https://harvesthq.github.io/chosen/,在多选区域中,您可以看到所有错误/报告及其相关 ID 的列表。甚至只是一个 ID 列表!

在典型的视图中,您会看到上面的内容。

我该怎么做才能让它正常工作?

让我给你我自己的代码来告诉你我的意思(代码被大大削减以使问题更容易):

Report.cs(模型)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace BugTracker.Models
{
    public class Report
    {
        //For User
        public int ID { get; set; }
        public String Name { get; set; }
        public String Description { get; set; }
        public String Solution { get; set; }    
    }
}

AdminReport.cshtml(查看)

@model BugTracker.Models.Report
@{
    ViewBag.Title = "Report";
    Layout = "~/Views/Shared/_Layout.cshtml";
}


<h1>@Model.Name</h1>
Description: @Model.Description <br /> <br />
Solution: @Model.Solution    <br /> <br>

以及用于编辑的表单...

AdminReportForm.cshtml

@model  BugTracker.ViewModels.UserReportViewModel

@{
    ViewBag.Title = "Issue Form";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Update Issue</h1>    
@Model.Report.Name <br />    
@using (Html.BeginForm("SaveAdmin", "Report"))
{
    <div class="form-group">
        <label>Solution</label>
        @Html.TextAreaFor(m => m.Report.Solution, new { @class = "form-control", @rows="10"})
    </div>
    @Html.HiddenFor(m => m.Report.ID)
    <button type="submit" class="btn btn-primary">Save</button>
}

我的视图模型(真正的视图模型包含几个附加字段):

UserReportViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BugTracker.Models;
using System.Web.Mvc;

namespace BugTracker.ViewModels
{
    public class UserReportViewModel
    {
        public Report Report { get; set; }    
    }
}

控制器...

(对于 AdminReport.cshtml)

    public ActionResult Admin(int id)
    {
        var report = _context.Reports.SingleOrDefault(c => c.ID == id);
        if (report == null)
            return HttpNotFound();

        var viewModel = new UserReportViewModel
        {
            Report = report,
        };

        return View("AdminReport", report);
    }

对于 AdminReportForm.cshtml

    public ActionResult EditAdmin(int id)
    {
        var report = _context.Reports.SingleOrDefault(c => c.ID == id);
        if (report == null)
            return HttpNotFound();

        var viewModel = new UserReportViewModel
        {
            Report = report,
        };

        return View("AdminReportForm", viewModel);
    }

最后是我的帖子:

    [HttpPost]
    [ValidateInput(false)]
    public ActionResult SaveAdmin(UserReportViewModel viewModel)
    {
        if (viewModel.Report.ID == 0)
            _context.Reports.Add(viewModel.Report);
        else
            var reportInDb = _context.Reports.Single(c => c.ID == viewModel.Report.ID);

        _context.SaveChanges();
        return RedirectToAction("ReportAll", "Report");

    }

【问题讨论】:

  • 感谢您询问如何使其正常工作,但我想知道读者是否需要更多关于您正在寻求的帮助的指导。例如,这是一个 UI 设计问题吗? SQL/数据库/模型/连接问题?你的代码目前做了什么,它与你想要的有什么不同?

标签: asp.net-mvc asp.net-mvc-4


【解决方案1】:

您可以将报表集合添加到您的视图模型中吗? 然后您可以使用 linq 过滤报告并填充下拉列表。

namespace BugTracker.ViewModels
{
    public class UserReportViewModel
    {
        public Report Report { get; set; }
        public List<Report> Reports {get; set;}
    }
}

【讨论】:

  • 我真的很喜欢这个主意!这对于用户可以选择多个报告的表单视图来说是完美的。但是,我会用什么来让我的报告模型保存用户选择的值?
  • 取得进展。按照建议,我使用了以下建议: public List Reports {get; set;} 为了实际保存数据,我在 Report 模型中添加了以下内容: public Virtual ICollection Reports {get; set;} 也就是说,我仍然在表单上苦苦挣扎。我正在尝试做这样的事情:@Html.DropDownListFor(m =&gt; m.Reports, new MultiSelectList(Model.Reports, "ID", "Name"), "Select Priority", new { id = "relatedbugs", multiple = "multiple" }) 但是,我不太确定如何使用这个访问我的列表。执行这行代码的正确方法是什么?
  • “但是,我的报告模型将使用什么来保存用户选择的值?”您可以根据需要向视图模型中添加任意数量的对象。创建另一个列表,List SelectedReports。然后在您的 post 控制器中,您可以将该对象传递到您的上下文中并更新数据库。
  • 为什么不使用标签助手而不是@html.DropDownList? docs.microsoft.com/en-us/aspnet/core/mvc/views/…
【解决方案2】:

我终于能够解决这个问题 - 感谢大家的帮助!以下是我的解决方法:

首先,在我的“Report.cs”文件中,我添加了以下内容:

public String RelatedBugs {get; set;}
public String[] RelatedBugsArray {get; set;}

在我的视图模型“UserReportViewModel.cs”中,我添加了以下内容:

public IEnumerable<Report> Report {get; set;}

表格给了我一些问题。我最初使用的是 DropDownBoxFor,但对于多选,您实际上需要使用 ListBoxFor(它仍然可以与 DropDownBoxFor 一起使用,但问题是当您尝试编辑表单时它无法预填充它。)所以,在 AdminReportForm.cshtml,我有以下内容:

@Html.ListBoxFor(m => m.Report.RelatedBugsArray, new MultiSelectList(Model.Reports, "ID", "Name"), new {id = "relatedbugs"})

要使用所选脚本,我首先通过以下链接进行设置:Use Chosen jQuery plugin in MVC Asp Net

在同一份报告中,我让我的 ListBoxFor 使用我的 Chosen 脚本:

@section scripts{
<script>
$(function () {
$("#relatedbugs").chosen();
});
</script>
}

现在,剩下的就是控制器了。我关心两个动作:编辑和保存动作。 EditAdmin 和 Admin 操作将具有相同的代码:

if (report.RelatedBugs != null)
     report.RelgatedBugsArray = report.RelatedBugs.Split(',');

对于 SaveAdmin 操作,我们只需要这样做:

if (viewModel.Report.RelatedBugsArray == null)
     viewModel.Report.RelatedBugs = null;
else
     viewModel.Report.RelatedBugs = string.Join(",", viewModel.Report.RelatedBugsArray);

基本上,我们所做的是将报告 ID 作为一个数组,并将它们放入一个字符串中,每个元素之间用逗号分隔。当我们将它反馈给视图时,通过用逗号分隔每个元素,将字符串转换为数组。

再次感谢所有建议!

【讨论】:

    猜你喜欢
    • 2015-10-06
    • 2017-08-25
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    相关资源
    最近更新 更多