Binding ListBox with a model in MVC3

Naresh picture Naresh · Aug 13, 2012 · Viewed 15.3k times · Source

My model is

public class SiteConfig
{
    public SiteConfig()
    {

    }

    public int IdSiteConfig { get; set; }
    public string Name { get; set; }
    public byte[] SiteLogo { get; set; }
    public string Brands { get; set; }
    public string LinkColour { get; set; }

    public IEnumerable<SiteBrand> SiteBrands { get; set; }
}

and

public class SiteBrand
{
    public int Id { get; set; }
    public int SiteId { get; set; }
    public int BrandId { get; set; }

    public Brand Brand { get; set; }
    public SiteConfig SiteConfig { get; set; }
}

public class Brand
{
    public int BrandId { get; set; }
    public string Name { get; set; }

    public IEnumerable<SiteBrand> SiteBrands { get; set; }
}

I am following Data Base first approach. Each SiteConfig record can contain one or more Brand. So Brand is saving to another table called SiteBrand.

SiteBrand contains the forign key reference to both SiteConfig(on IdSiteConfig) and Brand(BrandId).

When I am creating a SiteConfig I want to display all the available Brand as list box where user can select one or many record(may not select any brand).

But when I bind my view with the model how can I bind my list box to the list of brands and when view is posted how can I get the selected brands.

And I have to save the SiteConfig object to database with the selected Items. And this is my DB diagram.

This is my DAL which saves to db.

public SiteConfig Add(SiteConfig item)
    {
        var siteConfig = new Entities.SiteConfig
            {
                Name = item.Name,
                LinkColour = item.LinkColour,
                SiteBrands = (from config in item.SiteBrands
                              select new SiteBrand {BrandId = config.BrandId, SiteId = config.SiteId}).
                    ToList()
            };
        _dbContext.SiteConfigs.Add(siteConfig);
        _dbContext.SaveChanges();
        return item;
    }

DB Schema

Can somebody advide how to bind the list box and get the selected items.

Thanks.

Answer

Shyju picture Shyju · Aug 13, 2012

Add a new Property to your SiteConfig ViewModel of type string array. We will use this to get the Selected item from the Listbox when user posts this form.

public class SiteConfig
{
  //Other properties here
  public string[] SelectedBrands { get; set; }  // new proeprty
  public IEnumerable<SiteBrand> SiteBrands { get; set; }
}

In your GET action method, Get a list of SiteBrands and assign to the SiteBrands property of the SiteConfig ViewModel object

public ActionResult CreateSiteConfig()
{
    var vm = new SiteConfig();
    vm.SiteBrands = GetSiteBrands();
    return View(vm);
}

For demo purposes, I just hard coded the method. When you implement this, you may get the Data From your Data Access layer.

public IList<SiteBrand> GetSiteBrands()
{
    List<SiteBrand> brands = new List<SiteBrand>();
    brands.Add(new SiteBrand { Brand = new Brand { BrandId = 3, Name = "Nike" } });
    brands.Add(new SiteBrand { Brand = new Brand { BrandId = 4, Name = "Reebok" } });
    brands.Add(new SiteBrand { Brand = new Brand { BrandId = 5, Name = "Addidas" } });
    brands.Add(new SiteBrand { Brand = new Brand { BrandId = 6, Name = "LG" } });
    return brands;
}

Now in your View, which is strongly typed to SiteConfig ViewModel,

@model SiteConfig
<h2>Create Site Config</h2>
@using (Html.BeginForm())
{
  @Html.ListBoxFor(s => s.SelectedBrands, 
                new SelectList(Model.SiteBrands, "Brand.BrandId", "Brand.Name"))
  <input type="submit" value="Create" />
}

Now when user posts this form, you will get the Selected Items value in the SelectedBrands property of the ViewModel

[HttpPost]
public ActionResult CreateSiteConfig(SiteConfig model)
{
    if (ModelState.IsValid)
    {
        string[] items = model.SelectedBrands;
        //check items now
        //do your further things and follow PRG pattern as needed
    }
    model.SiteBrands = GetBrands();
    return View(model);
}

enter image description here