在 Foreach 或 For 循环中使用 EditorFor (ASP.NET MVC + RAZOR)

2024-06-19

我目前正在实施一个家谱我的 ASP.NET MVC 项目中的系统。为了设置家庭成员之间的关系,我需要每行显示两个 ComboBox/DropDownList 来定义一个成员与另一个成员之间的关系。

首先我将分享我的代码,然后我将解释到目前为止我尝试过的方法以及最终的结果。

视图模型

public class FamilyTreeRelationshipViewModel
{

    [ScaffoldColumn(false)]
    public string FromMemberId { get; set; }

    [ScaffoldColumn(false)]
    public string ToMemberId { get; set; }


    public Member FromMember { get; set; }
    public IEnumerable<Member> ToMembers { get; set; }


    [UIHint("FTComboBox")]
    [AdditionalMetadata("BindTo", "relationships")]
    [Required]
    [Display(Name = "From Relationship")]
    public string FromRelationship { get; set; }


    [UIHint("FTComboBox")]
    [AdditionalMetadata("BindTo", "relationships")]
    [Required]
    [Display(Name = "To Relationship")]
    public string ToRelationship { get; set; }
}

控制器

public class FamilyTreeController : Controller
{
    private AppMVC db = new AppMVC();


    public ActionResult Index(Guid? cid, Guid? mid)
    {

        if (cid == null && mid == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.NotFound);
        }


        var frommember = db.Member.FirstOrDefault(x => x.MemberId == mid && x.CaseId == cid && x.Deleted == false);
        var tomembers = db.Member.Where(x => x.CaseId == cid && x.MemberId != mid.Value && x.Deleted == false).ToList();


        ViewBag.cid = cid;
        ViewBag.mid = mid;

        PopulateRelationship();


        var familyTreeRelationshipViewModel = new FamilyTreeRelationshipViewModel
        {
            FromMember = frommember,
            ToMembers = tomembers,
        };

        return View(familyTreeRelationshipViewModel);
    }



    public void PopulateRelationship()
    {
        var relationship = db.RelationshipDD
        .Where(c => c.Deleted == false && c.Code != "PA")
        .OrderBy(c => c.OrderIndex)
        .Select(c => new RelationshipDDViewModel
        {
            Code = c.Code,
            Definition = c.Definition
        })
        .ToList();

        ViewData["relationships"] = relationship;

    }

}

组合框的编辑器模板

@model object

@{
    var bindto = ViewData.ModelMetadata.AdditionalValues["BindTo"].ToString();
    var fieldname = ViewData.ModelMetadata.PropertyName;
    var prefix = ViewData.TemplateInfo.HtmlFieldPrefix;

}

@(Html.Kendo().ComboBoxFor(m => m)
          .Filter("contains")
          .Placeholder(ViewData.ModelMetadata.DisplayName)
          .DataTextField("Definition")
          .DataValueField("Code")
          .HtmlAttributes(new { style = "width: 100%", Id = prefix})
          .BindTo((System.Collections.IEnumerable)ViewData[bindto])

          )

@Html.ValidationMessageFor(m => m, "", new { @class = "mdc-text-red-400" })

为了向每一行显示一个新结果,我使用了foreach在视图中:

@if (Model.ToMembers != null)
{
    if (Model.ToMembers.Any())
    {
        foreach (var othermembers in Model.ToMembers.OrderBy(x => x.MemberNumberSuffix))
        {
            @Html.EditorFor(m => m.ToRelationship)
            @Html.EditorFor(m => m.FromRelationship)
        }
    }
}

As you see below in the screenshot, only ComboBoxes in the first row were rendered. I assume it's because of the same control Id for each ComboBox. I checked the browser developer tools (F12), all of them had the same Id. ForEach

后来我想我应该使用 For 而不是 Foreach ,看看会发生什么:

@if (Model.ToMembers != null)
{
    if (Model.ToMembers.Any())
    {
        for (var i = 0; i < Model.ToMembers.Count(); i++)
        {
            var othermembers = Model.ToMembers.ToList()[i];

            @Html.EditorFor(m => m.ToRelationship[i])
            @Html.EditorFor(m => m.FromRelationship[i])
        }
    }
}

As you see below in the screenshot, all of the ComboBoxes are gone and everything has been rendered as Char. The only difference here is that each control/input has it's own Id and that's good but not good as I was expecting. For

毕竟,我决定使用内置 DropDownList (MVC) 来实现此目的,并且结果相同。因为我认为 Telerik 控制有问题。

我什至尝试直接在视图中使用组合框而不是编辑者,结果不同了。每行都被单独渲染并成功,但它又是 Char 类型,甚至错误消息也这么说。通常应该说“来自关系字段是必需的”。

@if (Model.ToMembers != null)
{
    if (Model.ToMembers.Any())
    {
        for (var i = 0; i < Model.ToMembers.Count(); i++)
        {

            @(Html.Kendo().ComboBoxFor(m => m.ToRelationship[i])
            .Filter("contains")
            .Placeholder(ViewData.ModelMetadata.DisplayName)
            .DataTextField("Definition")
            .DataValueField("Code")
            .HtmlAttributes(new { style = "width: 100%" })
            .BindTo((System.Collections.IEnumerable)ViewData["relationships"])
            )

            @(Html.Kendo().ComboBoxFor(m => m.FromRelationship[i])
            .Filter("contains")
            .Placeholder(ViewData.ModelMetadata.DisplayName)
            .DataTextField("Definition")
            .DataValueField("Code")
            .HtmlAttributes(new { style = "width: 100%" })
            .BindTo((System.Collections.IEnumerable)ViewData["relationships"])
            )
        }
    }
}

Screenshot: For Direct


问题

  1. 为什么我不能使用 EditorFor 来达到此目的?
  2. 为什么类型更改为 Char?我该如何解决这个问题?
  3. 有什么替代方法可以实现这一目标吗?

在此先感谢您的帮助!


首先,解释一下你的错误。您不能使用foreach循环生成form集合的控件。它会生成重复的name无法绑定回集合的属性(并且重复id无效的 html 属性)。你需要使用一个for循环,或者更好的自定义EditorTemplate。你的第二个错误(当你使用for循环)是因为您绑定的属性是string,因此绑定到m => m.ToRelationship[i]绑定到一个字符(typeofChar) 在里面string.

真正的问题是您的视图模型不正确,并且与视图中的显示/编辑内容无关,并且您需要将下拉列表绑定到集合中的属性。

此外,您使用 2 个组合框ToRelationship and FromRelationship会导致很多潜在的错误,你应该重新定义你的Relationship表包含(例如)以下字段

ID, Relationship, MaleReverseRelationship, FemaleReverseRelationship

所以典型的行可能包含

1, Son, Father, Mother
2, Wife, Husband, NULL
3, Niece, Uncle, Aunt

那么你需要一个下拉列表,如果杰克和罗杰的关系是Son,你知道相反的关系是Father(假设你的Member模型有一个字段Gender)。这将极大地简化您的视图模型,使 UI 更简单,并防止用户选择错误的反向关系时出现错误。

您尚未提供有关其他表格/模型的任何信息,但您需要MemberRelationShip带字段的表

ID, Member (FK to Members), OtherMember(FK to Members), RelationShip(FK to Relationships).

然后你需要 2 个视图模型,一个用于父视图模型Member以及建立关系的人

public class ParentMemberVM
{
    public int ID { get; set; }
    public string Name { get; set; }
    .... other properties to display
    public IEnumerable<MemberVM> Members { get; set; }
    public IEnumerable<SelectListItem> RelationshipList { get; set; }
}
public class MemberVM
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Relationship { get; set; }
}

那么你需要一个EditorTemplate for MemberVM

/Views/Shared/EditorTemplates/MemberVM.cshtml

@model MemberVM
@Html.HiddenFor(m => m.ID)
@Html.DisplayFor(m => m.Name)
@Html.DropDownListFor(m => m.Relationship, (IEnumerable<SelectListItem>)ViewData["relationships"])

并在主视图中

@model ParentMemberVM
....
@using (Html.BeginForm())
{
    @Html.HiddenFor(m => m.ID)
    @Html.DislayFor(m => m.Name)
    @Html.EditorFor(m => m.Members, new { relationships = Model.RelationshipList })
    <input type="submit" value="Save" />
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Foreach 或 For 循环中使用 EditorFor (ASP.NET MVC + RAZOR) 的相关文章

  • 在 C# 中格式化 Resharper 属性的支持字段

    有没有办法控制 Resharper 放置其支持字段的位置 目前 它试图让他们在班级中名列前茅 我希望他们能去到酒店的正上方 还没有
  • asm、asm 易失性内存和破坏性内存之间的区别

    在实现无锁数据结构和定时代码时 通常需要抑制编译器的优化 通常人们使用asm volatile with memory在 clobber 列表中 但有时你会看到asm volatile或者只是一个简单的asm破坏记忆 这些不同的语句对代码生
  • C++ 构造函数根据参数类型调用另一个构造函数

    我有这门课 class XXX public XXX struct yyy XXX std string private struct xxx data 第一个构造函数 使用结构 很容易实现 第二 我可以将一个字符串以特定的格式分开 解析
  • Linq Any 始终返回 true

    我已经使用 Linq to Entities 多年 但这是我第一次遇到这个问题 我有Tips and Items表 每个提示可以有很多项目 我的数据库中只有 3 个项目 编辑项目时 我想确保GivenId对于具有相同提示的项目 字段是唯一的
  • Motif 库的水平绘制的 RowColumn 类 (C)?

    我正在使用 Motif Library 来完成我的工作 如果有人不熟悉这个库 您可以在这里找到文件列表https packages ubuntu com xenial amd64 libmotif dev filelist https pa
  • 改装和授权标头

    目前 我正在向我的请求添加授权标头 如下所示 文件 SomeFile cs public interface ITestApi Get api test id Task
  • 安装/编译 pylzma(lzma python 绑定)

    我已经向作者提出了这个问题website http www joachim bauch de projects pylzma comment page 1 comment 5211 但我想我也可以在这里问 我一直在尝试使用以下设置安装 py
  • 从 pdf 和 word 文件中提取文本

    如何在 C 中从 pdf 或 word 文件中提取文本 删除粗体 图像和其他富文本格式媒体 您可以使用专为索引服务设计 由索引服务使用的过滤器 它们旨在从各种文档中提取纯文本 这对于在文档内部进行搜索非常有用 您可以将其用于 Office
  • 除非我在开​​始时声明变量,否则为什么会收到“错误未声明的标识符”?

    当我有以下情况时 include stdafx h include
  • dotnet core 创建文件名中不含“CoreFxPipe_”的命名管道

    使用以下命令创建命名管道时命名管道客户端流 or 命名管道服务器流dotnet core 的类中 关联的 管道 看起来实际上是一个套接字 已自动将 CoreFxPipe 添加到文件名的前面 有没有一种非黑客的方法来防止这种行为 我只是希望文
  • 以 asp-for 作为参数的自定义 ViewComponent

    我想把这个包装起来
  • 在实体框架中不使用 Dispose 或 using()

    我一路上正在编写一个网络应用程序并学习实体框架 如果我做错了什么 我很好奇 我在查询时没有使用过 dispose 或 using 语句 我的存储库示例 public User GetUserById int sessionId var us
  • 从 Windows 选择声音并播放它们

    我有一个 WinForms 应用程序 该应用程序有一个 首选项 部分 用户可以在其中选择显示警报时播放哪些声音 是否可以有一个组合框 用户可以从 Windows 存储的声音中进行选择 例如 紧急停止 紧急蜂鸣 等 这些可以在 控制面板 gt
  • 使用 C# 在 XML 文档中查找特定值的好方法是什么?

    我正在调用 Oracle 公开的 WebService 它接受 ItemID 的输入并向我返回相应的 Item Number 我想获取从响应中包含的 XML 返回的项目编号 XML 看起来像这样
  • 设置了 OFN_ALLOWMULTISELECT 标志的 GetOpenFileName()

    我正在尝试使用 GetOpenFileName 通用对话框调用来弹出打开对话框并允许用户选择多个文件 我设置了 OFN ALLOWMULTISELECT 标志 并设置了 OFN EXPLORER 因此我得到了 新样式 文件选择框 当我设置
  • boost::bind 会导致开销吗?

    我目前正在从事网络软件方面的工作 它有一个主要类 server这显然代表一个服务器实例 A server实例可以发送请求 并通过回调通知用户响应 代码如下 class server public typedef boost function
  • TPL架构问题

    我目前正在开展一个项目 我们面临并行处理项目的挑战 到目前为止没什么大不了的 现在来说说问题 我们有一个 ID 列表 我们定期 每 2 秒 为每个 ID 调用一个 StoredProcedure 需要单独检查每个项目的 2 秒 因为它们是在
  • SQlite 查询 - 如何检索多列数据?

    我很难在网上找到一个关于使用 xcode 和 cocos2dx 从 SQlite DB 获取多个值的工作示例 这是我的sql查询 char sql query 100 sprintf sql query SELECT FROM SQList
  • 系统.安全.加密与 PCLCrypto

    我们正在删除系统中的许多共享功能并将其移植到 PCL 库中 我在使用 PCLCrypto 时遇到问题 我正在获取数据库中的一些现有数据 并尝试使用相同的算法对其进行解密 我得到了值 但末尾有 16 个额外字节 这些字节都是垃圾 参见下面的代
  • MVC 4 Razor 如果拆分 div 标签

    我有以下 MVC 4 Razor 代码 for int i 1 i lt 100 i if currentCol 1 Html Raw div class row Need to do this because can t have a o

随机推荐