DropDownList在ASP.Net MVC中无法正常工作

时间:2022-11-12 00:20:50

I am quite confused with how to effectively use the Html.DropDownList helper for ASP.NET MVC.

我对如何有效地使用ASP.NET MVC的Html.DropDownList帮助器感到困惑。

Background: I have a 5-page form, which saves data to the form each time "Next" is clicked. Users may navigate back and forth between sections, so previous sections will already be pre-populated with previously-entered data.

背景:我有一个5页的表单,每次单击“下一步”时都会将数据保存到表单中。用户可以在各部分之间来回导航,因此之前的部分已经预先填充了先前输入的数据。

This works for TextBoxes. But not DropDownLists. I have tried a load of different methods, including:

这适用于TextBoxes。但不是DropDownLists。我尝试了很多不同的方法,包括:

I have a ViewModel such taht I have got my lists and my Model (a LINQ-to-SQL generated class) as properties. eg:

我有一个ViewModel这样的taht我有我的列表和我的模型(一个LINQ-to-SQL生成的类)作为属性。例如:

public class ConsultantRegistrationFormViewModel
{
    public IConsultantRegistration ConsultantRegistration { get; private set; }

    public SelectList Titles { get; private set; }
    public SelectList Countries { get; private set; }
    public SelectList Currencies { get; private set; }
    public int CurrentSection { get; private set; }

    private ConsultantRegistrationFormViewModel(IConsultantRegistration consultantRegistration)
    {
        ConsultantRegistration = consultantRegistration;


        CurrentSection = 1;

        Titles = new SelectList(new string[] { "Mr", "Mrs", "Miss", "Ms", "Dr", "Sir" });
        Countries = new SelectList(countries.Select(q => q.Name));
        Currencies = new SelectList(currencies,"CurrencyCode","FriendlyForm");
    }
}

My Controller's Edit Action on GET looks like:

我的控制器在GET上的编辑操作如下所示:

public class ConsultantRegistrationController : Controller
{
        public IConsultantRegistrationRepository ConsultantRegistrationRepository { get; private set; }
        public ICountryRepository CountryRepository { get; private set; }
    public IEnumerable<ICountry> Countries { get; private set; }

    public ConsultantRegistrationController()
    {
        ConsultantRegistrationRepository = RepositoryFactory.CreateConsultantRegistrationRepository();
        CountryRepository = RepositoryFactory.CreateCountryRepository();

        Countries = CountryRepository.GetCountries().ToArray();
    }


    public ActionResult Edit(Guid id, int sectionIndex)
    {
        IConsultantRegistration consultantRegistration = ConsultantRegistrationRepository.GetConsultantRegistration(id);

        SelectList bankBranchCountriesSelectList = new SelectList(Countries, "BankBranchCountry", "CountryName", consultantRegistration.BankBranchCountry);
        ViewData["bankBranchCountrySelectList"] = bankBranchCountriesSelectList;

        return View(new ConsultantRegistrationFormViewModel(consultantRegistration,sectionIndex,  Countries,Currencies));
    }
}

With my View doing:

用我的View做:

        <%: Html.DropDownList("ConsultantRegistration.BankBranchCountry",ViewData["bankBranchCountrySelectList"] as SelectList) %>

This gives me the error:

这给了我错误:

DataBinding: 'IWW.ArrowPay.ConsultantRegistration.Data.Country' does not contain a property with the name 'BankBranchCountry'.

DataBinding:'IWW.ArrowPay.ConsultantRegistration.Data.Country'不包含名为'BankBranchCountry'的属性。

Which it does, have a look at the schema of this property:

它做了什么,看看这个属性的架构:

public interface IConsultantRegistration
{
    Guid ID { get; set; }


    [DisplayName("Branch Country")]
    string BankBranchCountry { get; set; }

}

(My LINQ-to-SQL type ConsultantRegistration implemented IConsultantRegistration)

(我的LINQ-to-SQL类型ConsultantRegistration实现了IConsultantRegistration)

It seems that it is trying to bind to the wrong type, though?

看来它似乎试图绑定到错误的类型,但是?

If I use this in my view (and use my Controller's Countries property):

如果我在我的视图中使用它(并使用我的Controller的Countries属性):

        <%: Html.DropDownList("ConsultantRegistration.BankBranchCountry ",Model.Countries,"(select a Country)") %>

I get the saved value fine, but my model doesn't update on POST.

我得到保存的值很好,但我的模型不会在POST上更新。

And if I use this in my view:

如果我在我的观点中使用它:

        <%: Html.DropDownListFor(model=>model.ConsultantRegistration.BankBranchCountry ",Model.Countries,"(select a Country)") %>

I get the list, and it POSTs the selected value back, but does not pre-select the currently selected item in my model on the view.

我得到了列表,并且它返回了所选值,但是没有在视图中预先选择模型中当前选定的项目。

So I have a bit of the solution all over the place, but not all in one place.

所以我在整个地方都有一些解决方案,但不是全部在一个地方。

Hope you can help fill in my ignorance.

希望你能帮助填补我的无知。

2 个解决方案

#1


1  

Ok, I solved it. Proper hacky, but it gets the job done.

好的,我解决了。适当的hacky,但它完成了工作。

I'm using the ViewData in my view:

我在我的视图中使用ViewData:

                <%: Html.DropDownList("bankBranchCountrySelectList", ViewData["bankBranchCountrySelectList"] as SelectList)%>

With the following in my controller:

在我的控制器中有以下内容:

        public ActionResult Edit(Guid id, int sectionIndex)
        {
            IConsultantRegistration consultantRegistration = ConsultantRegistrationRepository.GetConsultantRegistration(id);

            ViewData["bankBranchCountrySelectList"] = Countries.Select(q => new SelectListItem() { Text = q.Name, Value = q.Name, Selected = (q.Name.Trim().Equals(consultantRegistration.BankBranchCountry, StringComparison.InvariantCultureIgnoreCase)) }); // bankBranchCountriesSelectList;

            return View(new ConsultantRegistrationFormViewModel(consultantRegistration,sectionIndex,  Countries,Currencies));
        }



        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(Guid id, int sectionIndex, FormCollection formValues)
        {
            IConsultantRegistration consultantRegistration = ConsultantRegistrationRepository.GetConsultantRegistration(id); 

            UpdateModel(consultantRegistration);
                    ViewData["bankBranchCountrySelectList"] = Countries.Select(q => new SelectListItem() { Text = q.Name, Value = q.Name, Selected = (q.Name.Trim().Equals(consultantRegistration.BankBranchCountry, StringComparison.InvariantCultureIgnoreCase)) });

            IEnumerable<RuleViolation> ruleViolations = consultantRegistration.GetRuleViolations(sectionIndex);
            if (ruleViolations.Count() == 0)
            {

// ...
            }
            else
            {
                ModelState.AddRuleViolations(ruleViolations);
                return View(new ConsultantRegistrationFormViewModel(consultantRegistration, sectionIndex, Countries, Currencies));
            }


    }

Not ideal and breaks clean coding. No idea why it works, but that seems to be what MVC is all about with "convention over configuration".

不理想,打破干净的编码。不知道它为什么会起作用,但这似乎是MVC与“约定优于配置”的关系。

#2


0  

This article was written with Multi-Select Lists in mind, but the principle applies equally to a single-selection drop down list:

本文是在考虑多选列表的情况下编写的,但该原则同样适用于单选下拉列表:

http://www.stevefenton.co.uk/Content/Blog/Date/201002/Blog/How-To-Handle-Multiple-Select-Lists-In-ASP-NET-MVC/

#1


1  

Ok, I solved it. Proper hacky, but it gets the job done.

好的,我解决了。适当的hacky,但它完成了工作。

I'm using the ViewData in my view:

我在我的视图中使用ViewData:

                <%: Html.DropDownList("bankBranchCountrySelectList", ViewData["bankBranchCountrySelectList"] as SelectList)%>

With the following in my controller:

在我的控制器中有以下内容:

        public ActionResult Edit(Guid id, int sectionIndex)
        {
            IConsultantRegistration consultantRegistration = ConsultantRegistrationRepository.GetConsultantRegistration(id);

            ViewData["bankBranchCountrySelectList"] = Countries.Select(q => new SelectListItem() { Text = q.Name, Value = q.Name, Selected = (q.Name.Trim().Equals(consultantRegistration.BankBranchCountry, StringComparison.InvariantCultureIgnoreCase)) }); // bankBranchCountriesSelectList;

            return View(new ConsultantRegistrationFormViewModel(consultantRegistration,sectionIndex,  Countries,Currencies));
        }



        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(Guid id, int sectionIndex, FormCollection formValues)
        {
            IConsultantRegistration consultantRegistration = ConsultantRegistrationRepository.GetConsultantRegistration(id); 

            UpdateModel(consultantRegistration);
                    ViewData["bankBranchCountrySelectList"] = Countries.Select(q => new SelectListItem() { Text = q.Name, Value = q.Name, Selected = (q.Name.Trim().Equals(consultantRegistration.BankBranchCountry, StringComparison.InvariantCultureIgnoreCase)) });

            IEnumerable<RuleViolation> ruleViolations = consultantRegistration.GetRuleViolations(sectionIndex);
            if (ruleViolations.Count() == 0)
            {

// ...
            }
            else
            {
                ModelState.AddRuleViolations(ruleViolations);
                return View(new ConsultantRegistrationFormViewModel(consultantRegistration, sectionIndex, Countries, Currencies));
            }


    }

Not ideal and breaks clean coding. No idea why it works, but that seems to be what MVC is all about with "convention over configuration".

不理想,打破干净的编码。不知道它为什么会起作用,但这似乎是MVC与“约定优于配置”的关系。

#2


0  

This article was written with Multi-Select Lists in mind, but the principle applies equally to a single-selection drop down list:

本文是在考虑多选列表的情况下编写的,但该原则同样适用于单选下拉列表:

http://www.stevefenton.co.uk/Content/Blog/Date/201002/Blog/How-To-Handle-Multiple-Select-Lists-In-ASP-NET-MVC/