views:

196

answers:

2

I have following problem. In my view model I defined some list properties as follows:

public class BasketAndOrderSearchCriteriaViewModel
{
    List<KeyValuePair> currencies;
    public ICollection<KeyValuePair> Currencies
    {
        get
        {
            if (this.currencies == null)
                this.currencies = new List<KeyValuePair>();
            return this.currencies;
        }
    }

    List<KeyValuePair> deliverMethods;
    public ICollection<KeyValuePair> DeliveryMethods
    {
        get
        {
            if (this.deliverMethods == null)
                this.deliverMethods = new List<KeyValuePair>();
            return this.deliverMethods;
        }
    }
 }

This view model is embedded in another view model:

 public class BasketAndOrderSearchViewModel
 {
    public BasketAndOrderSearchCriteriaViewModel Criteria
    {
        [System.Diagnostics.DebuggerStepThrough]
        get { return this.criteria; }
    }
 }

I use 2 action methods; one is for the GET and the other for POST:

[HttpGet]
public ActionResult Search(BasketAndOrderSearchViewModel model){...}

[HttpPost]
public ActionResult SubmitSearch(BasketAndOrderSearchViewModel model){...}

In the view I implement the whole view model by using the EditorFor-Html Helper which does not want to automatically display DropDownLists for List properties! 1. Question: How can you let EditorFor display DropDownLists?

Since I could not figure out how to display DropDownLists by using EditorFor, I used the DropDownList Html helper and filled it through the view model as follows:

    public IEnumerable<SelectListItem> DeliveryMethodAsSelectListItem()
    {
        List<SelectListItem> list = new List<SelectListItem>();
        list.Add(new SelectListItem()
        {
            Selected = true,
            Text = "<Choose Delivery method>",
            Value = "0"
        });
        foreach (var item in this.DeliveryMethods)
        {
            list.Add(new SelectListItem()
            {
                Selected = false,
                Text = item.Value,
                Value = item.Key
            });
        }

        return list;
    }

My 2. question: As you can see I pass my view model to the action metho with POST attribute! Is there a way to get the selected value of a DropDownList get binded to the passed view model? At the moment all the DropDownList are empty and the selected value can only be fetched by the Request.Form which I definitely want to avoid!

I would greatly appreciate some ideas or tips on this!

A: 

Let's try to take on this one:

Answer to Question 1: How can you let EditorFor display DropDownLists?

When you call Html.EditorFor() you can pass extra ViewData values to the EdiorTemplate View:

<%: Html.EditorFor(model => Model.Criteria, new { DeliveryMethods = Model.DeliveryMethods, Currencies = Model.Currencies}) %>

Now you have ViewData["DeliveryMethods"] and ViewData["Currencies"] initialized and available inside your EditorTemplate.

In your EditorTemplate you somehow need to call and convert those entries into DropDowns / SelectLists. Assuming you've got an ascx file of type System.Web.Mvc.ViewUserControl<BasketAndOrderSearchCriteriaViewModel> you could do the following:

<%: Html.LabelFor(model => model.DeliveryMethods) %>
<%: Html.DropDownList("SelectedDeliveryMethod", new SelectList(ViewData["DeliveryMethods"] as IEnumerable, "SelectedDeliveryMethod", "Key", "value", Model.SelectedDeliveryMethod)) %>

Same goes for the Currencies.

<%: Html.LabelFor(model => model.Currencies) %>
<%: Html.DropDownList("SelectedCurrency", new SelectList(ViewData["Currencies"] as IEnumerable, "SelectedDeliveryMethod", "Key", "value", Model.SelectedCurrency)) %>

This setup will make your DeliveryMethodAsSelectListItem() obsolete and you can use any kind of list. Means you are not bound to KeyValuePairs. You'll just need to adjust your call on Html.DropDownList() from now on.

As you can see, I have introduced some new properties to your BasketAndOrderSearchCriteriaViewModel:

Model.SelectedDeliveryMethod
Model.SelectedCurrency

They are used to store the currently selected value.

Answer to Question 2: Is there a way to get the selected value of a DropDownList get binded to the passed view model?

In the EditorFor template we are passing the newly created Model.SelectedDeliveryMethod and Model.SelectedCurrency properties as the SelectedValue Parameter (See 4th Overload of the DropDownList Extension Method).

Now that we have the View doing it's job: How can we get the currently selected value inside the POST Action?

This is really easy now:

[HttpPost]
public ActionResult SubmitSearch(BasketAndOrderSearchViewModel model)
{
    ...
    var selectedDeliveryMethod = model.Criteria.SelectedDeliveryMethod;
    var selectedCurrency model.Criteria.SelectedDeliveryMethod;
    ...
}

Note: I don't have an IDE to test it right now, but it should do the trick or at least show you in which direction to go.

Shaharyar
Thanks for your quick reply to my question! It gave me a good hint in which direction I have to go! I will provide my final solution in here when it is done!
tmesi
A: 

For those like me that got to this post these days I'd recommend you to fully download the tutorial from http://www.asp.net/mvc/tutorials/mvc-music-store-part-1 which covers this and most of the common techniques related with .NET MVC applications.

Anyway Really usefull your post and answers man (If I could vote you I would :)

Frederic