【问题标题】:How to get data of EditorFor with nested viewmodels如何使用嵌套视图模型获取 EditorFor 的数据
【发布时间】:2011-04-04 16:04:22
【问题描述】:

这是我的情况 -

我有两个嵌套视图模型:

  1. <%=Html.EditorFor(x => x.DisplayEntitiesWithRadioboxesViewModel)%><br />

位于它们的父级 (StructureViewModel) 中,我可以轻松填充嵌套的 ViewModel 并将其传递给主视图:

在控制器内 - 示例

var moveDepartment = new StructureViewModel();
moveDepartment.DisplayEntitiesWithRadioboxesViewModel = fullDepartmentList.Select(x => new DisplayEntityViewModel
            {
                Id = x.Id,
                Path = x.Path,
                PathLevel = x.PathLevel,
                Description = x.Description,
            });

return View(moveDepartment);

EditorTemplete - 示例

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Site.Areas.Administration.ViewModel.DisplayEntityViewModel>>" %>
<table class="aligncenter"><%
  if (Model != null)
  {
    foreach (var entity in Model)
    {%>
      <tr class="tRow">
        <td style="text-align:left; text-indent:<%=Html.Encode(entity.PathLevel)%>em">
          <%=Html.Encode(entity.Description)%>
          <%=Html.RadioButton("radiobutton",entity.Id)%>
        </td>              
      </tr><%    
    }
  }%>
</table>


namespace Site.Areas.Administration.ViewModel
{
    public class DisplayEntityViewModel
    {
        public int Id { get; set; }
        public string Path { get; set; }
        public string PathLevel { get; set; }
        public string Description { get; set; }   
    }
}

但是,当我尝试撤回此信息时,嵌套的 ViewModel 为空:

[HttpPost]
public ActionResult Move(StructureViewModel StructureViewModel)

当我将鼠标悬停在 StructureViewModel 上时,它只包含父 ViewModel 中的数据集。例如:可以看到一个隐藏的值,但是 DisplayEntitiesWithRadioboxesViewModel = null。

我知道如何访问 DisplayEntitiesWithRadioboxesViewModel 的唯一方法是使用 FormCollection 并遍历 FormCollection 并从嵌套的 ViewModel 中提取我需要的信息。

然而,这似乎并不正确,正如我发现的那样,我必须使用 FormCollection 中的值重新填充 DisplayEntitiesWithRadioboxesViewModel,例如,如果发生错误并且用户需要发送回同一个视图。

我已尝试搜索网络/书籍,但找不到解决方案。

有没有更好的方法?

提前感谢您的帮助。

你为什么要使用 EditorFor 简单的下拉菜单,很容易 与 DropDownFor 一起使用

现在已更改为使用 DropDownFor。

什么是关键 DisplayEntitiesWithRadioboxesViewModel FormCollection 中的值

{string[3]}
[0] = "DisplayEntitiesWithRadioboxesViewModel.radiobutton"
[1] = "Action"
[2] = "OldParentId"

克莱尔:-)

【问题讨论】:

    标签: asp.net asp.net-mvc-2 viewmodel


    【解决方案1】:

    你能告诉我EditorFor 的样子吗?以及为什么你使用EditorFor 来做一个简单的下拉菜单,它很容易与DropDownFor 一起使用。

    FormCollection 中的DisplayEntitiesWithRadioboxesViewModel 值的Key 是什么

    如果我理解正确,您有一个视图,其中包含一些父信息,同时在同一个视图中这两个字段的多次迭代。对吗?

    那我知道怎么解决了。

    【讨论】:

    • 您好 Stefanvds,我已经修改了上面的问题来回答您的问题。我有一个父视图,其中包含一个 DisplayEntitiesWithRadioboxesViewModel 实例。 DisplayEntitiesWithRadioboxesViewModel 是 IEnumerable。感谢 Clare 详细信息,但是我只在其中使用一次嵌套视图
    • 单选按钮的键是“DisplayEntitiesWithRadioboxesViewModel.radiobutton”是逻辑,因为在您的编辑器中,您有一个名称为“radiobutton”的单选按钮。如果我做对了,一切正常,只有单选按钮值不会在您的视图模型中得到解析。我认为最好的方法是创建一个 RadioButtonList 助手,如下所述:geekswithblogs.net/michelotti/archive/2009/08/05/…。我之前用 CheckBoxList 做过同样的事情,效果很好。另外,也许用下拉列表替换单选按钮列表?
    【解决方案2】:

    您的问题很常见,一旦您了解了它的工作原理,就很容易解决。

    现在你有一个视图模型,它的属性是IEnumerable&lt;T&gt;(不管泛型参数是什么)。您正在尝试将项目传递给视图并在响应返回时使用相同的值填充IEnumerable&lt;T&gt;,使用最初写入页面的值,并使用所选项目进行扩充(至少从您发布的代码中)无论如何,这将有助于您在问题中说明您的确切意图)。您在这里遇到的问题是您必须将这些值以可以返回的方式发送到页面。

    现在让我说一下,您可能应该使用这种技术。如果您需要服务器端,最好只返回选择并再次生成列表。

    从外观上看,您希望返回整个列表,然后查找被选中的项目,这毕竟是下拉或单选按钮组的点。为了取回选择,控制器操作的参数必须具有与传回的变量匹配的属性。在这种情况下,您似乎为所有单选按钮使用参数名称 radiobutton(相同对下拉列表成立,只有它使用列表的名称)。无论选择哪一个,与它关联的值都会以该名称返回。 MVC 框架负责尝试找到具有尽可能多的指定名称的适当操作。

    您需要为您的操作参数使用一个新类,该类包含所有要提交回服务器的字段名称的属性!或者,当然您也可以简单地将 radiobutton 属性添加到您的 StructureViewModel 中。事实上,您会注意到它已经在尝试设置该值,只是它当前不存在于您的视图模型中。但是,您仍然不会收到原始列表,但没关系,因为即使您确实收到了原始列表,您也没有任何标识符可以让您知道选择了哪个项目!

    希望这可以帮助您了解正在发生的事情,如果您有更多问题,请提出。

    【讨论】:

      【解决方案3】:

      我建议您在任何地方都使用强类型帮助器,这样您就不必担心控件的命名。以下是如何进行:

      型号:

      public class DisplayEntityViewModel
      {
          public int Id { get; set; }
          public string Path { get; set; }
          public string PathLevel { get; set; }
          public string Description { get; set; }
      }
      
      public class StructureViewModel
      {
          public IEnumerable<DisplayEntityViewModel> DisplayEntitiesWithRadioboxesViewModel  { get; set; }
      }
      

      控制器:

      public class HomeController : Controller
      {
          public ActionResult Index()
          {
              var moveDepartment = new StructureViewModel();
              moveDepartment.DisplayEntitiesWithRadioboxesViewModel = new[] 
              {
                  new DisplayEntityViewModel
                  {
                      Id = 1,
                      Path = "some path 1",
                      PathLevel = "some path level 1",
                      Description = "some description 1"
                  },
                  new DisplayEntityViewModel
                  {
                      Id = 2,
                      Path = "some path 2",
                      PathLevel = "some path level 2",
                      Description = "some description 2"
                  },
              };
              return View(moveDepartment);
          }
      
          [HttpPost]
          public ActionResult Index(StructureViewModel StructureViewModel)
          {
              return View(StructureViewModel);
          }
      }
      

      主视图 (~/Views/Home/Index.aspx):

      <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SomeNs.Models.StructureViewModel>" %>
      
      <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
      
      <% using (Html.BeginForm()) { %>
          <table class="aligncenter">
              <%= Html.EditorFor(x => x.DisplayEntitiesWithRadioboxesViewModel) %>
          </table>
          <input type="submit" value="Go" />
      <% } %>
      
      </asp:Content>
      

      编辑器模板 (~/Views/Home/EditorTemplates/DisplayEntityViewModel.ascx)

      <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ToDD.Models.DisplayEntityViewModel>" %>
      
      <tr class="tRow">
          <td style="text-align:left; text-indent:<%=Html.Encode(Model.PathLevel)%>em">
              <%= Html.Encode(Model.Description) %>
      
              <!-- Remember that you need to place input fields for each property
                   that you expect to get back in the submit action
              -->
              <%= Html.HiddenFor(x => x.Description) %>
              <%= Html.TextBoxFor(x => x.Path) %>
          </td>              
      </tr>
      

      现在提交表单,所有内容都应该正确绑定。需要注意的重要一点是,编辑器模板的强类型为DisplayEntityViewModel 而不是IEnumerable&lt;DisplayEntityViewModel&gt;,就像您的情况一样。当您在主视图中编写时:

      <%= Html.EditorFor(x => x.DisplayEntitiesWithRadioboxesViewModel) %>
      

      框架会自动检测到该属性是一个集合,并为该集合的每个项目调用编辑器模板,因此您不再需要循环遍历元素,从而使您的代码更加优雅。


      更新:

      使用下拉列表也很简单:结帐this answer

      【讨论】:

      • 虽然这确实将所有提交给浏览器的值返回给服务器,但仍然无法将选中的值抓取回来,我相信这是他的误解。
      • @NickLarsen,我不清楚下拉菜单。在她编辑之后,OP 声明她使用了一个下拉菜单但没有显示她的代码并且仍然在谈论radiobutton。使用 DropDownListFor 辅助方法可以很好地与编辑器模板配合使用并生成正确的名称,所以我不明白您说这个 仍然无法取回所选值是什么意思。跨度>
      • 如果她正在创建下拉列表或单选按钮列表,她正在尝试从列表中选择单个项目。据我了解,她的问题是使用任一方法检索选定的值,并且必须解析表单数据以检索它,但希望将其作为她的视图模型的属性检索。简单的解决方法是添加所用列表的名称,在本例中为 radiobutton 作为她的视图模型的属性,她将不再需要在表单数据中挖掘她想要的值。
      猜你喜欢
      • 1970-01-01
      • 2017-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多