简体   繁体   中英

Bind a ViewModel to a DropDownListFor with a third value besides dataValueField/dataTextField

When I show a list of testplanViewModels in my View and the user selects one the SelectedTestplanId is returned to the Controller post action. What should also be returned is the TemplateId which belongs to the SelectedTestplanId.

When the AutoMapper definition is run the Testplan.TestplanId is implicitly copied over to the TestplanViewModel.TestplanId . The same could be done by providing a TemplateId on the TestplanViewModel. When the user selects now a "TestplanViewModel" in the View, how can I attach the TemplateId to the controller action to access it there? The DropDownList does not allow 2 dataValueFields!

CreateMap<Testplan, TestplanViewModel>().ForMember(dest => dest.Name, opt => opt.MapFrom(src => string.Format("{0}-{1}-{2}-{3}", src.Release.Name, src.Template.Name, src.CreatedAt, src.CreatedBy)));

public ActionResult OpenTestplanViewModels()
{
    IEnumerable<Testplan> testplans = _testplanDataProvider.GetTestplans();          
    var viewModel = new OpenTestplanViewModel
    {
        DisplayList = Mapper.Map<IEnumerable<Testplan>, IEnumerable<TestplanViewModel>>(testplans)
    };
    return PartialView(viewModel);
}


public class TestplanViewModel
{      
    public int TestplanId { get; set; }     
    public string Name { get; set; }           
}


public class OpenTestplanViewModel
{
    [Required(ErrorMessage = "No item selected.")]
    public int SelectedTestplanId { get; set; } 
    public IEnumerable<TestplanViewModel> DisplayList { get; set; }       
}

OpenTestplanViewModel

@using (Html.BeginForm("Open", "Testplan"))
{ 
    @Html.ValidationSummary(false)      
    @Html.DropDownListFor(x => x.SelectedTestplanId, new SelectList(Model.DisplayList, "TestplanId", "Name"), new { @class = "listviewmodel" })  
}

Solution :

 public class OpenTestplanViewModel
    {
        [Required(ErrorMessage = "No item selected.")]
        public string TestplanIdAndTemplateId { get; set; } 
        public IEnumerable<TestplanViewModel> DisplayList { get; set; }

        public int SelectedTestplanId
        {
            get
            {
                return Convert.ToInt32(TestplanIdAndTemplateId.Split(new[] { '_' }).First());
            }
        }
        public int SelectedTemplateId
        {
            get
            {
                return Convert.ToInt32(TestplanIdAndTemplateId.Split(new[] { '_' }).Last());
            }
        }   
    }

 CreateMap<Testplan, TestplanViewModel>()
                .ForMember(d => d.Name, o => o.MapFrom(src =>  string.Format("{0}-{1}-{2}-{3}", src.Release.Name, src.Template.Name, src.CreatedAt, src.CreatedBy)))
                .ForMember(d => d.TestplanIdAndTemplateId, o => o.MapFrom(src => src.TestplanId + "_" + src.TemplateId));

HTML doesn't really work that way. If you want more than one value returned from the post for the dropdown (the helper generates a select element), you'll have to create a property on your view model that you then parse within the controller.

For instance, if you had two integer ID fields, the combined property could create a value that looks something like 23_42 . You could then use the Split method to get the correct values ( 23 & 42 ) back.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM