“在编辑 Razor 页面上显示所选下拉列表”

Have Selected Dropdown Appear on Edit Razor Page

提问人:MelB 提问时间:6/17/2022 最后编辑:MelB 更新时间:7/12/2022 访问量:1334

问:

注意:从原始帖子修改而来。 一些模型/属性名称已随着更多编辑而更改。

我有一个创建页面,它将使用几个下拉列表。对于编辑页面,我希望创建页面中的所选值显示为所选的下拉选项,但仍希望它是所有值的下拉列表,以便在创建页面上选择的值不正确时,用户可以选择新值。

例如,如果用户在创建页面上从“苹果”、“桃子”和“梨”的下拉列表中选择了“桃子”并发布,当他们进入编辑页面时,我希望下拉列表显示“桃子”作为所选值,但允许用户选择“苹果”或“梨”(如果他们希望更改它)。

这是我在edit.cshtml页面上的下拉列表(两者的设置方式相同):

<td style="width: 25%">
   <div class="mb-3">
      <label asp-for="InfoSite.Specialty"></label>
      <select asp-for="InfoSite.Specialty" id="Select1" class="form-select"> 
         <option value="">---Select Specialty---</option>
         @foreach(var item in Model.DisplayMDSpecialtyData)
             {
               <option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)" disabled="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)">@item.Description</option>
             }
       </select>
   </div>
</td>
<td style="width: 25%">
   <div class="mb-3">
       <label asp-for="InfoSite.ResType"></label>                      
       <select asp-for="InfoSite.ResType" id="Select2" class="form-select">
           <option value="">---Select Residence Type---</option>
           @foreach(var item in Model.DisplayResTypeData)
              {
                 <option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.ResType?true:false)" disabled="@(item.ID.ToString()==Model.InfoSite.ResType?true:false)">@item.Description</option>
              }
        </select>
    </div>
</td>

这是我在edit.cshtml.cs上的内容(包括2个下拉列表的信息):

namespace PHECWeb.Pages.InfoSites;

[BindProperties]

public class EditModel : PageModel
{
    private readonly ApplicationDbContext _db;
    public InfoSite InfoSite { get; set; }
    public EditModel(ApplicationDbContext db)
    {
        _db = db;
    }

    public IEnumerable<ResType> DisplayResTypeData { get; set; }
    public IEnumerable<MDSpecialty> DisplayMDSpecialtyData { get; set;  }

    public async void OnGet(int? ID)
    {
        InfoSite = _db.InfoSite.Find(ID);
        DisplayResTypeData = await _db.ResType.ToListAsync();
        DisplayMDSpecialtyData = await _db.MDSpecialty.ToListAsync();
    }

    public async Task<IActionResult> OnPost()
    {
        if (ModelState.IsValid)
        {
            _db.InfoSite.Update(InfoSite);
            await _db.SaveChangesAsync();
            TempData["success"] = "Site Information updated successfully.";
            return RedirectToPage("Index");
        }
        return Page();
    }
}

我在 @foreach(Model.DisplayMDSpecialtyData 中的 var 项)上收到可怕的 System.NullReferenceException:“对象引用未设置为对象的实例。

System.NullReferenceException Error

我迫切需要帮助来克服这个问题。:(有人能否能够添加一些见解(通俗地说,因为我是所有这些的新手)关于我需要对此代码进行哪些编辑才能摆脱此错误?我用谷歌和YouTube搜索过,但由于我目前的知识水平太低,所以我对我所看到的内容并不了解。我理解这个概念,我只是不明白修复的位置(视图与.cs)或修复的确切语法。我尽我最大的努力学习,如上所述,只有在我自己进行大量搜索之后才提出这个问题。请善待。

asp.net-core 选择 下拉列表 razor-pages

评论


答:

0赞 Rena 6/20/2022 #1

您需要了解以下事项:

首先,通过使用您当前的代码,您将生成与该值匹配的选项值和与该值匹配的选项文本。selectIDDescription

<select>
    <option value="ID1">Description1</option>
    <option value="ID2">Description2</option>
    //....
</select>

然后匹配所选选项值,即 的值。因此,您需要确保 的值和应该保持不变。asp-for="InfoSite.ResType"IDResCategoryResTypeID

最后,对于“编辑”页面,如果 的值与选项之一 value( value) 相同。下拉列表将自动选择此选项。但是不能这样做。InfoSite.ResTypeIDdisabled

这是您可以遵循的完整工作演示:

public class ResCategory
{
    public int ID { get; set; }
    public string? Description { get; set; }
}
public class InfoSite
{ 
    public int ID { get; set; }
    public string? ResType { get; set; }
}

视图

<select asp-for="InfoSite.ResType" id="Select2" class="form-select">
    <option value="">---Select Residence Type---</option>
    @foreach(var item in Model.DisplayResCatData)
    {
        <option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.ResType?true:false)" disabled="@(item.ID.ToString()==Model.InfoSite.ResType?true:false)">@item.Description</option>
    }
</select>

PageModel(页面模型)

public class EditModel : PageModel
{
    public IEnumerable<ResCategory> DisplayResCatData { get; set; }
    public InfoSite InfoSite { get; set; }
    public void OnGet(int? id)
    {
        //for easy testing, I just hard coded here......
        //InfoSite = await _db.InfoSite.FindAsync(id);
        InfoSite = new InfoSite()
        {
            ID = 1,
            ResType = "2"
        };
        DisplayResCatData = new List<ResCategory>()
        {
            new ResCategory(){ID=1,Description="aa"},
            new ResCategory(){ID=2,Description="bb"},
            new ResCategory(){ID=3,Description="cc"}
        };
    }
}

评论

0赞 MelB 6/20/2022
嗨,蕾娜,感谢您的解释。恐怕我可以跟着走,直到页面模型,然后我就迷路了。你说 //为了便于测试,只是在这里硬编码...,但是我如何从 ResCategory 数据库中获取 Description 值以发布到 InfoSite 数据库?我不想对值进行硬编码,因为用户将更新 ResCategory 数据库并添加到该下拉列表中。我希望这一切都自动发生。谢谢。
0赞 Rena 6/21/2022
嗨,@MelB,可以从数据库中获取值。await _db.ResCategory.select(a=>a.Description).ToListAsync();DescriptionResCategory
0赞 MelB 6/23/2022
我正在按照您的建议使用上述代码,但在运行程序时出现错误。程序在 @foreach(var 项 Model.DisplayResCatData)(在页面视图中)上停止,并突出显示 Model.DisplayResCatData,并显示错误:System.NullReference.Exception: 'Object reference not set to an instance of an object.'我不确定我可能错过了什么?
0赞 Rena 6/23/2022
嗨,@MelB,那是因为是空值。您需要设置断点并检查它是否包含任何数据。Model.DisplayResCatDataModel.DisplayResCatData
0赞 MelB 6/23/2022
我以为整个目的?是为了消除空值错误吗?
-1赞 MelB 7/12/2022 #2

这是另一个非常困难的绊脚石,只需进行非常简单的更改即可使代码正常工作。

<option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)" disabled="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)">@item.Description</option>

只需要“disabled=...”删除后如下所示:

<option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)">@item.Description</option>

然后,所选值将显示在“编辑”页面上。