如何使用嵌套的视图模型获取EditorFor的数据

时间:2010-08-27 07:15:01

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

这是我的情况 -

我有两个嵌套的视图模型:

  1. <%=Html.EditorFor(x => x.DisplayEntitiesWithRadioboxesViewModel)%><br />
  2. 位于其父级(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);
    

    编辑完成 - 示例

    <%@ 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为null:

    [HttpPost]
    public ActionResult Move(StructureViewModel StructureViewModel)
    

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

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

    然而,这似乎不正确,因为我在我发现然后必须使用DisplayEntitiesWithRadioboxesViewModel中的值重新填充FormCollection,例如,如果发生了错误,则用户需要被发送回相同的视图。

    我尝试过搜索网页/书籍但找不到解决方案。

    有更好的方法吗?

    提前感谢您的帮助。

      

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

    现在已经改变为使用DropDownFor。

      

    什么是关键   DisplayEntitiesWithRadioboxesViewModel   FormCollection中的值

    {string[3]}
    [0] = "DisplayEntitiesWithRadioboxesViewModel.radiobutton"
    [1] = "Action"
    [2] = "OldParentId"
    
    克莱尔: - )

3 个答案:

答案 0 :(得分:3)

一旦你理解了它的工作原理,你的问题很常见并且很容易修复。

现在您有一个视图模型,其属性为IEnumerable<T>(与通用参数无关)。您正尝试将项目传递给视图,并在响应返回时使用相同的值填充IEnumerable<T>,使用最初写入页面的值,并使用所选项目进行扩充(至少从您的代码中添加)无论如何已发布,这将有助于你在问题中陈述你的确切意图)。您遇到的问题是您必须以可以返回的方式将这些值发送到页面。

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

从事物的外观来看,您希望返回整个列表,然后查找所选项目,即在下拉列表或单选按钮组之后。为了获得选择,控制器操作的参数必须具有与传回的变量匹配的属性。在这种情况下,您看起来对所有单选按钮使用参数名称radiobutton(同样适用于下拉列表,只有它使用列表的名称)。选择哪一个,与该名称相关联的值将以该名称返回。 MVC框架负责尝试找到具有尽可能多的名称的适当操作。

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

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

答案 1 :(得分: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<DisplayEntityViewModel>。在主视图中,您可以写下:

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

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


更新:

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

答案 2 :(得分:0)

你能告诉我EditorFor看起来如何吗?为什么使用EditorFor进行简单的下拉菜单,这很容易与DropDownFor一起使用。

Key

DisplayEntitiesWithRadioboxesViewModel值的FormCollection是多少?

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

然后我知道如何解决这个问题。

相关问题