提问人:MelB 提问时间:2/6/2023 最后编辑:RenaMelB 更新时间:2/7/2023 访问量:1536
如何使用多选下拉列表绑定多个值
How to Bind Multiple Values with Multi-Select Dropdown List
问:
我有一个多选下拉列表,我需要从中获取值并放置在另一个数据表中 - 事件表。
我正在从这个模型中提取下拉列表的值:
using System.ComponentModel.DataAnnotations;
namespace DWITracker.Model
{
public class Charge
{
[Key]
public int Id { get; set; }
[Required]
[Display(Name = "Charge")]
public string ChargeCode { get; set; }
[Required]
[Display(Name = "Charge Description")]
public string ChargeDesc { get; set; }
}
}
这是我的 Create.cs:
using DWITracker.Data;
using DWITracker.Model;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
namespace DWITracker.Pages.Incidents;
[BindProperties]
public class CreateModel : PageModel
{
private readonly ApplicationDbContext _db;
public Incident Incident { get; set; }
public CreateModel(ApplicationDbContext db)
{
_db = db;
}
public IEnumerable<City> DisplayPIAddressCityData { get; set; }
public IEnumerable<County> DisplayPIAddressCountyData { get; set; }
public IEnumerable<Ethnicity> DisplayPIEthnicityData { get; set; }
public IEnumerable<int> Charge { get; set; }
public IEnumerable<SelectListItem> ChargeList { get; set; }
public async Task<PageResult> OnGet()
{
await _db.City.Select(a => a.CityName).ToListAsync();
DisplayPIAddressCityData = await _db.City.ToListAsync();
await _db.County.Select(a => a.CountyName).ToListAsync();
DisplayPIAddressCountyData = await _db.County.ToListAsync();
await _db.Ethnicity.Select(a => a.EthnicityName).ToListAsync();
DisplayPIEthnicityData = await _db.Ethnicity.ToListAsync();
var charges = from c in _db.Charge
select c;
ChargeList = charges.Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.ChargeCode });
return Page();
}
public async Task<IActionResult> OnPost()
{
await _db.Incident.AddAsync(Incident);
await _db.SaveChangesAsync();
TempData["success"] = "Incident Information added successfully.";
return RedirectToPage("Index");
}
}
以下是我观点的相关部分:
<td style="width: 40%">
<div class="mb-3">
<label asp-for="Incident.ArrestCharges" class="control-label"></label>
<select asp-for="Incident.ArrestCharges" class="form-select" multiple="multiple" asp-items="Model.ChargeList">
<option value="">Select Applicable Charge(s)</option>
</select>
</div>
</td>
现在,如果我从多选下拉列表中选择多个项目,则只会将第一个选择的 Id 值放入 Incident.ArrestCharges 列中。
我希望它放置一个逗号分隔的多个费用代码(不是 ID)列表,如下所示:VTL 1192-1、VTL 1192-2、VTL 1192-2
希望能得到一些关于我需要删除、添加或更改的内容的指导。这是我第一次创建多选下拉列表并绑定它。谢谢!
答:
好的,那么如果用户选择 2 个、1 个或 5 个选项?
然后,您需要在此处添加 2 个、1 个或 5 个 recrods。
你不能这样做:
例如:tblPeople
FirstName: John
LastName: Smith
HotelsBooked: 123, 832, 992
那么,通过存储 3 个值(我预订的酒店),那么现在怎么办?
您将如何报告,或使用sql来查询我预订了哪些酒店?
答:你不能!!
因此,不要突然开始将多个 ID 推入一列,因为从那时起,您就破坏了使用 SQL 查询该数据的所有可能性。
换句话说,你要打破你的关系模型,你这样做了,那么你的整个系统就无法报告我预订了哪些酒店(在上面的例子中)。
既然列数据类型是“数字”和“id”?那么,当然,你不能只是塞进多个 ID 值。正如我上面的例子所示,如果为该列使用字符串,您可以推入多个值,但如前所述,您这样做的 INSTANT 是什么?就在这时,你打破了关系模型,但这并不是真正的关系“巨无霸”,而是现在你没有实际的方法来使用SQL来查询这些数据。(甚至将“ID”转换回正确的值,以便在报表甚至网页中显示。
因此,在上面,如果我想允许该人预订多个酒店,我不能突然加入多个值,而是需要创建一个新的子表。在我看来,这将是
tblPeople - 我上面关于这个人的信息。
tblPeopleBookedInhotels - 这是新的子表。
因此,代替上面的(我试图将多个 id 推入该列,我现在将得到这个:
所以,老:
新增功能:
因此,您可以看到我们希望预订多家酒店的“即时”,然后我们就不能使用用于保存一个值和一个 ID 的一列 (hotel_id)。
问题更严重,因为你的列数据类型无疑是数字类型,因此你甚至不能塞进一串“id's”。
更糟糕的是,你不想这样做,因为从那时起,任何查询该数据的能力也都消失了。
因此,不要将多个值推入该列(不允许多个值)。
您必须获取用户选择,然后遍历这些选择,向这个新表添加一个全新的行,该表现在可以包含许多酒店预订的“列表”。
我的意思是,您可以尝试将其 kluge 化,并将一个列类型从“数字”更改为字符串,然后尝试将多个值作为字符串插入,但随后您破坏了所有假设并期望该列中只有一个“id”值的现有软件。
编辑:写出多行的示例
好吧,假设我们有“人”,然后是他们想去的酒店列表框或其他什么。
所以,我们有这个:
所以,我们将有人物,一张酒店表,当然还有我们的表,允许每个人进行多个酒店预订。
所以,tblHotels预订了。
我们实际上有这个:
因此,假设我们有一些标记来显示 Person。
没什么特别的,只是一些标记,还有那个酒店列表框。
所以,我们有这个标记(不是那么重要)。
<div id="EditRecord" runat="server" style="float:left;display: normal;border:solid 2px;padding:15px;border-radius:12px">
<h3>Edit Bookings</h3>
<div style="float:left" class="iForm">
<label>First Name</label>
<asp:TextBox ID="tFN" runat="server" f="FirstName" Width="140" /> <br />
<label>Last Name</label>
<asp:TextBox ID="tLN" runat="server" f="LastName" Width="140" /> <br />
<label>City</label>
<asp:TextBox ID="tCity" runat="server" f="City" Width="140" /><br />
<label>Prov</label>
<asp:TextBox ID="tProvince" runat="server" f="Province" Width="75" ></asp:TextBox>
</div>
<div style="float:left;margin-left:20px;margin-top:-30px" class="iForm">
<label>Notes</label> <br />
<asp:TextBox ID="txtNotes" runat="server" Width="400" TextMode="MultiLine"
Height="150px" f="Notes" ></asp:TextBox> <br />
</div>
<div style="float:left;margin-left:20px;margin-top:-30px" class="iForm">
<label>Select Hotels</label> <br />
<asp:ListBox ID="lstHotels" runat="server"
DataValueField="id"
DataTextField="HotelName"
SelectionMode="Multiple" Height="180px" Width="183px">
</asp:ListBox>
</div>
<div style="clear:both;height:20px"></div>
<button id="cmdSave" runat="server" class="btn myshadow" onserverclick="cmdSave_ServerClick" >
<span aria-hidden="true" class="glyphicon glyphicon-floppy-saved"> Save</span>
</button>
<button id="cmdCancel" runat="server" class="btn myshadow" style="margin-left:15px" >
<span aria-hidden="true" class="glyphicon glyphicon-arrow-left"> Back/Cancel</span>
</button>
<button id="cmdDelete" runat="server" class="btn myshadow" style="margin-left:15px">
<span aria-hidden="true" class="glyphicon glyphicon-trash"> Delete</span>
</button>
</div>
好的,所以我们的代码必须加载一个人,并加载我们想要选择的酒店的列表框。
因此,要加载的代码是这样的:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["PKID"] = 16; // assume passed value from preivous page
LoadData();
}
}
void LoadData()
{
string strSQL =
@"SELECT id, HotelName FROM tblHotelsA
ORDER BY HotelName";
lstHotels.DataSource = General.MyRst(strSQL); // load list box
lstHotels.DataBind();
strSQL = $@"SELECT * from People WHERE ID = {ViewState["PKID"]}";
DataTable dtPerson = General.MyRst(strSQL);
General.FLoader(EditRecord, dtPerson.Rows[0]);
}
现在我们看到/有了这个:
因此,保存代码必须:
将任何编辑保存为一个人,然后为列表框中选择的每家酒店写出一个新行。
所以,保存代码是这样的:
protected void cmdSave_ServerClick(object sender, EventArgs e)
{
int PKID = (int)ViewState["PKID"];
General.FWriter(EditRecord, PKID, "People"); // send form to database
// now save/process list box of multiple selected hotels
// create one new whole row for each hotel selected.
string strSQL = "SELECT * FROM tblHotelsBooked WHERE ID = 0";
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
DataTable dtBookedHotels = new DataTable();
dtBookedHotels.Load(cmdSQL.ExecuteReader());
foreach (ListItem OneHotel in lstHotels.Items)
{
if (OneHotel.Selected)
{
DataRow MyNewBooking = dtBookedHotels.NewRow();
MyNewBooking["People_ID"] = PKID;
MyNewBooking["Hotel_id"] = OneHotel.Value;
dtBookedHotels.Rows.Add(MyNewBooking);
}
}
SqlDataAdapter da = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder daU = new SqlCommandBuilder(da);
// now save/send all rows in data table back to database
da.Update(dtBookedHotels);
}
}
}
因此,现在我们为每个选定的酒店写出一行数据。
但是,在这个例子中?
我们现在的问题是,当我们返回页面再次编辑时。
现在,我们不仅要加载一个要编辑的 reocrd,还要加载列表框,其中包含可能的选择,并选择/突出显示每个现有酒店,以便用户可以“查看”和“知道”选择了哪些选项。
如果用户取消选择酒店,则必须从 tblHotelsBooked 中删除/删除该子行。
现在,如果这只是一个单一的值(如favorote food),或者类似的东西,那么这个UI可能会相当不错。但是,就我而言,鉴于我们正在选择(并添加)酒店给用户?
然后我们真的需要采用一个用户界面,用户可以在其中看到哪些酒店,添加更多酒店,并删除酒店。
所以,实际上,列表框应该变成一个类似表格的视图(比如网格视图)。
因此,当我们返回该 reocrd 时,我们可以更清楚地查看、选择、添加、删除、编辑、更改该信息。
所以,实际上,我们应该转储列表框,并使用某种类型的网格。
那么结果将是这样的:
现在,在上面的例子中,我们有“更多”而不是选定的列表。
那么,如果我们只有一个包含选定酒店的列表框?当然,但在这个例子中,我们需要“更多”,因为我想添加更多酒店,或者删除它们。
那么,如果我们“坚持”列表框呢?
然后,我们需要添加代码来选择-突出显示现有选择。
然后,当我们取消选择时,我们需要添加代码来“删除”子行。
评论
我希望它放置一个逗号分隔的多个收费代码(不是 ID)列表
这是因为您的下拉值已使用 Id 设置,请将该值更改为如下所示:ChargeCode
ChargeList = charges.Select(c => new SelectListItem { Value = c.ChargeCode, Text = c.ChargeCode });
并且多个下拉列表应与要求中的 type 属性匹配,因此您需要创建一个单独的属性来接收多个选定值,然后将此列表转换为带有逗号的字符串。最后,您可以将此字符串值设置为 。List<string>
List<string>
Incident.ArrestCharges
这是您可以遵循的完整工作演示:
页
@page
@model CreateModel
<form method="post">
<div class="mb-3">
<label asp-for="Incident.ArrestCharges" class="control-label"></label>
//change the tag helper value here...........
<select asp-for="MultiCharge" class="form-select" multiple="multiple" asp-items="Model.ChargeList">
<option value="">Select Applicable Charge(s)</option>
</select>
</div>
<input type="submit" value="Post" />
</form>
PageModel(页面模型)
[BindProperties]
public class CreateModel : PageModel
{
//more properties......
public Incident Incident { get; set; }
public IEnumerable<SelectListItem> ChargeList { get; set; }
public List<string> MultiCharge { get; set; } //receive the multiple selected values
public async Task<PageResult> OnGet()
{
//other not important code......
//var charges = from c in _db.Charge
// select c;
//hard-coding here is just for easy testing
var charges = new List<Charge>()
{
new Charge(){ChargeCode="aa",Id=1},
new Charge(){ChargeCode="bb",Id=2},
new Charge(){ChargeCode="xx",Id=3}
};
// change the Value here....
ChargeList = charges.Select(c => new SelectListItem { Value = c.ChargeCode, Text = c.ChargeCode });
return Page();
}
public async Task<IActionResult> OnPost()
{
//convert list into string with comma.....
Incident.ArrestCharges = String.Join(",", MultiCharge);
//.....
return RedirectToPage("Index");
}
}
评论
下一个:级联下拉列表 - 我错过了什么?
评论