MVC 5 ViewModel,带有可枚举属性的EditorTemplate

时间:2015-03-05 22:01:54

标签: c# asp.net-mvc asp.net-mvc-5

我试图找到最合适的方法来执行以下操作:

我有一个名为CharacterViewModel的字符编辑器的ViewModel。这个CharacterViewModel填充了一个Character对象,一个角色可以拥有的可用能力分数列表,它们在另一个表中。

我为下拉菜单创建了一个编辑模板,我试图找到一种方法来恢复已编辑的能力列表。我似乎无法让他们回到控制器上。

这是ViewModel代码:

    public class CharacterViewModel : DbContext
    {
            public Character Character { get; set; }

            [UIHint("CharacterAbilityScores")]
            public IEnumerable<CharacterAbilityScore> CharacterAbilityScores { get; set; }

            public IEnumerable<SelectListItem> AbilityScoresSelectList { get; set; }

            public IEnumerable<AbilityModifiersAndBonusSpellDTO> AbilityModifiersAndBonusSpellDTO { get; set; }

            public CharacterViewModel()
                : base("name=CharacterModels")
            {
            }
    }

以下是填充ViewModel的控制器代码:

    public async Task<ActionResult> Edit(int? id)
    {
        Character character = db.Characters.Find(id);
        var model = new CharacterViewModel();
        model.Character = character;
        model.CharacterAbilityScores = character.CharacterAbilityScores;

        // Creating the list of ability scores for the view            
        model.AbilityScoresSelectList = from amabs in db.AbilityModifiersAndBonusSpells
                                        select new SelectListItem()
                                        {
                                            Value = amabs.score.ToString(),
                                            Text = amabs.score.ToString()
                                        };

        return View(model);
    }

控制器中的编辑方法签名(CharacterAbilityScores属性和其他复杂属性在返回时始终为空):

    public async Task<ActionResult> Edit(CharacterViewModel characterViewModel)

以下是编辑视图中的相关代码:

    @model CampaignManager.Models.CharacterViewModel
    @using (Html.BeginForm())
    {
            <div class="form-group">
                    @Html.EditorFor(model => model.CharacterAbilityScores, new { AbilityScoresSelectList = Model.AbilityScoresSelectList })
            </div>
    }

最后,编辑模板:

    @model IEnumerable<CampaignManager.Entities.CharacterAbilityScore>

    <table>
    @foreach (var abilityScore in Model)
    {
            <tr>
                    <td>@abilityScore.Ability.Abbreviation</td>
                    <td>
                            @{
                            if (ViewData["AbilityScoresSelectList"] != null)
                            {
                                    @Html.HiddenFor(z => abilityScore);
                                    @Html.HiddenFor(z => abilityScore.AbilityId);
                                    @Html.DropDownListFor(x => abilityScore.AbilityId, (IEnumerable<SelectListItem>)ViewData["AbilityScoresSelectList"], dropDownHTMLOptions);
                            }
                    }
                    </td>
            <tr>
    }
    </table>

我尝试了许多不同的HiddenFor技巧,存储了整个收藏品,存储了不同的ID ...我在那里迷失了一点点我会承认。也许我这样做是错的,我还需要另一种方法吗?

更新

以下是CharacterAbilityScore实体的模型:

public partial class CharacterAbilityScore
{
    [Key]
    [Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int CharacterId { get; set; }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int AbilityId { get; set; }

    public int AbilityScore { get; set; }

    public virtual Ability Ability { get; set; }

    public virtual AbilityModifiersAndBonusSpell AbilityModifiersAndBonusSpell { get; set; }

    public virtual Character Character { get; set; }
}

1 个答案:

答案 0 :(得分:1)

EditorFor()旨在通过集合中的EditorTemplatetype集合(在您的情况下,您已将EditorTemplate的模型设为集合(而不是type),然后给每个元素一个重复的id属性(无效的html)和重复的name属性(不能绑定到集合)。

将模板(Views/Shared/EditorTemplates/CharacterAbilityScore.cshtml)更改为:

@model CampaignManager.Entities.CharacterAbilityScore
<tr>
  <td>@Html.DisplatFor(m => m.Ability.Abbreviation)</td>
  <td>@Html.DropDownListFor(m => m.AbilityId, (IEnumerable<SelectListItem>)ViewData["AbilityScoresSelectList"])</td>
</tr>

并在主视图中

@model CampaignManager.Models.CharacterViewModel
@using (Html.BeginForm())
{
  <table>
    @Html.EditorFor(model => model.CharacterAbilityScores, new { AbilityScoresSelectList = Model.AbilityScoresSelectList })
  </table>
}

附注:

  1. 您尚未发布CharacterAbilityScore的模型,所以有 假设它包含属性Abbreviation(仅用于显示)和 AbilityId(与下拉列表相关联)。
  2. 您无法在复杂对象上使用@Html.HiddenFor()(值 将是对象的.ToString()输出并且具有 @Html.HiddenFor()与下拉列表相同的属性(和 位于@Html.DropDownListFor()之前)意味着你将绑定 回发后的隐藏输入(即原始值,而不是 从下拉列表中选择的值
  3. 我还建议您的视图模型不是从DbContext派生的。 视图模型的目的是定义您想要的属性 在视图中显示/编辑