-2

I have a publishers table and I have titles table. I am using Entity Framework v4.1. A publisher entity has titles property and it signifies how many titles this particular publisher has published (I am using pubs database). I want to create a checkbox list where all the titles are shown (all records of titles table) and the titles which this publisher has published should be checked. How can I do that?

I am only able to produce a DropDownlist so far using this code:

<tr>
            <td>
                Titles
            </td>
            <td>
                @Html.DropDownListFor(p => p.titles.ToList()[0], new SelectList(ViewBag.titles, "title_id", "notes"))
            </td>
        </tr>

How can I convert this to checkbox list?

Thanks in advance :)

EDIT: After reading Brian's post, I made some progress however when I submit the form no values are found:

I created a partial class of title:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MVCWebApp.Models
{
    public partial class title
    {

        public int Id { get; set; }
        public bool IsChecked { get; set; }
    }
}

This is my EditorTemplate for checkbox:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MVCWebApp.Models.title>" %>

<%= Html.HiddenFor(x => x.Id)%>
<%= Html.CheckBoxFor(x => x.IsChecked)%>
<%= Html.DisplayFor(x => x.title1)%>
<br />

From the page where I need checkboxlist I wrote this code:

 <td>
                @Html.EditorFor(p => ViewData["titles"])
            </td>

This is the actual (highly ineffecient due to nested loop) controller method which renders the page:

 public ActionResult Edit(string id)
        {
            using (PubsEntities entities = new PubsEntities())
            {
                publisher pub = entities.publishers.Include("titles").Where(p => p.pub_id == id).First();
                List<title> titles = entities.titles.ToList();
                foreach (var item in pub.titles)
                {
                   title tit = (from titleItem in titles where item.pub_id == titleItem.pub_id select item).First();
                    tit.IsChecked = true;
                }
                ViewData["titles"] = titles;
                return View(pub);
            }
        }

I get the master list of titles and those titles are published by a particular publisher is checked. However when the form is posted, the values are all null

This is my update method where the form is posted:

 public ActionResult Update(publisher modifiedPub, List<title> selectedTitle )
        {
            if (!ModelState.IsValid)
                return View("Edit", modifiedPub);

            using (PubsEntities entities = new PubsEntities())
            {

                publisher pub = entities.publishers.Where(p => p.pub_id == modifiedPub.pub_id).First();
                pub.pub_name = modifiedPub.pub_name;
                pub.state = modifiedPub.state;

                entities.SaveChanges();
                return RedirectToAction("Publishers");
            }
        }

Here the selectedTitle is null and even in modifiedPub.titles the count is 0. Can anybody tell me where is it wrong?

Thanks in advance :)

P.S: Do we really have to do so much just to get checkboxlist?

tereško
  • 58,060
  • 25
  • 98
  • 150
Jaggu
  • 6,298
  • 16
  • 58
  • 96
  • 1
    See this stackoverflow post; [http://stackoverflow.com/questions/4872192/checkboxlist-in-mvc3-0][1] [1]: http://stackoverflow.com/questions/4872192/checkboxlist-in-mvc3-0 – Brian Scott Jul 29 '11 at 10:14
  • @Brian: I am confused. Is this really what I am looking for? – Jaggu Jul 29 '11 at 10:28

1 Answers1

1

The following line is your problem:

@Html.EditorFor(p => ViewData["titles"])

Everytime you use the ViewData/ViewBag keywords in an ASP.NET MVC application you will have problems. The correct way of doing this is to use a view model. In this view model you will have a property Titles which will be a collection of the type you defined. And in your view you will simply:

@Html.EditorFor(p => p.Titles)

This of course would mean that you will have to modify your Edit controller action so that instead of returning this pub domain model to the view it uses your actual real view model.

Like this:

public class TitleViewModel
{
    public int Id { get; set; }
    public bool IsChecked { get; set; }
}

public class PublisherViewModel
{
    public IEnumerable<TitleViewModel> Titles { get; set; }

    ... some other properties of a publisher that you want to work on in your view    
}

and the controller:

public ActionResult Edit(string id)
{
    var publisher = _service.GetPublisher(id);

    var viewModel = new PublisherViewModel
    {
        Titles = publisher.Titles.Select(x => new TitleViewModel
        {
            Id = x.Name,
            IsChecked = true
        })
    };

    return View(model);
}

[HttpPost]
public ActionResult Update(PublisherViewModel model)
{
    if (!ModelState.IsValid)    
    {
        return View(model);
    }

    var publisher = ... map the view model to a domain model
    _service.UpdatePublisher(publisher);

    return RedirectToAction("Publishers");
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • I know but that is not what I want. `p.Titles` will only be a collection of titles which has been published by a particular publisher. I want to show all the records of titles tables that is why I stored it in ViewData. Please let me know if I am not clear about my requirement. – Jaggu Jul 29 '11 at 11:58
  • Oh my god. I got your point. But this is too much code just to get 1 checkboxlist. Is there no other solution for this? Also I noticed nobody teaches these real world things in any tutorial. They just show how to show textbox and get data inside it. – Jaggu Jul 29 '11 at 12:07
  • 1
    @Bob Lee Swagger, you could use [AutoMapper](http://automapper.codeplex.com/) to perform the mapping between your domain models and your view models. It would drastically simplify your controller actions where, as I showed in my post, the mapping was done manually. – Darin Dimitrov Jul 29 '11 at 12:12
  • Ok! one more thing. It should not be `Titles = publisher.Titles(...)` rather it should be `Titles = context.Titles(...)` because I need all titles to show up and then loop over titles and check the required ones (which are present in publisher.titles). – Jaggu Jul 29 '11 at 12:25