Search code examples
c#asp.net-mvchtml-selectwebgrid

How to bind an ID to the selected value of an @Html.DropDownList within a WebGrid


I have a View in my MVC project that has a WebGrid which is binded by an "Account" model that I passed into the View.

In my "Account" Controller I created a List of SelectedListItem's that I contains the DropDownList options which I then set to a ViewBag:

public ActionResult Index()
{
   var accounts = db.Accounts;
   var groups = db.Groups;

   List<SelectListItem> groupList = new List<SelectListItem>();
   foreach(var item in groups)
   {
       groupList.Add(new SelectListItem()
       {
            Value = item.group_id.ToString(),
             Text = item.group_name
       });
    }

    ViewBag.Groups = groupList;


    return View(accounts);
}

The DropDownList contains 3 entries with their value and text as follows:

1, One 2, Two 3, Three

My problem is getting the group_id (Value) of the binded data to properly display the group_name (Text) on the DropDownList.

This is what I have so far:

grid.Column("group_id","Group", format: (item) => @Html.DropDownList("GroupId", (List<SelectListItem>)ViewBag.Groups))

The DropDownList does contains all 3 values I mentioned previously, it just doesn't set the DropDownList to the proper one at all for all the binded Accounts, as the image shows:

Account WebGrid

I have edited this post to add my View code.

@model IEnumerable<Account>

@{
    ViewBag.Title = "Index";

    WebGrid grid = new WebGrid(Model, rowsPerPage: 10);
}

<h2>Fee Invoices</h2>


@grid.GetHtml(tableStyle: "table table-bordered",
 mode: WebGridPagerModes.All,
 firstText: "<< First",
 previousText: "< Prev",
 nextText: "Next >",
 lastText: "Last >>",
    columns: grid.Columns(
    grid.Column("account_name", "Account"),
    grid.Column("account_number", "Account Number"),
    grid.Column("as_of_date", "Date", format: (item) => string.Format("{0:MM/dd/yyyy}", item.as_of_date)),
    grid.Column("approved", "Approved", format: @<text><input id="select" class="box" name="select" type="checkbox" @(item.approved ? "checked='checked'" : "") value="@item.approved" /></text>),
    grid.Column("group_id","Group", format: (item) => @Html.DropDownList("GroupId", (List<SelectListItem>)ViewBag.Groups))
)


))

Solution

  • You can pass a Dictionary<int, string> of group_id and group_name to your view instead of the list of SelectListItem and then use it to create the DropDownList with the correct value selected.

    In the controller

    public ActionResult Index()
    {
       var accounts = db.Accounts;
       var groups = db.Groups;
    
       // this line creates a Dictionary<int, string> where group_id is the key and group_name the value
       var groupsNames = groups.ToDictionary(x => x.group_id, x => x.group_name);
    
       ViewBag.GroupsNames = groupsNames;
    
       return View(accounts);
    }
    
    

    Then in the view declare a function like this (usually before the html part)

    @functions
    {
        public List<SelectListItem> CreateSelectList(int groupId)
        {
            var newList = new List<SelectListItem>();
    
            foreach (var val in (Dictionary<int, string>)ViewBag.GroupsNames)
            {
                newList.Add(new SelectListItem
                {
                    Text = val.Value,
                    Value = val.Key.ToString(),
                    Selected = val.Key == groupId
                });
            }
    
            return newList;
        }
    }
    

    and use it to populate the drop down list

    grid.Column("group_id", "Group", format: (item) => Html.DropDownList("GroupId", CreateSelectList((int)item.group_id)))
    

    Or, if you don't need the drop down list but instead just want to display the name of the group you can do

    grid.Column("group_id", "Group", format: (item) => ((Dictionary<int, string>)ViewBag.GroupsNames)[item.group_id])
    

    and in this case you don't need the function.