views:

1893

answers:

4

Hi guys,

I'd like to take two tables and populate a gridview with the results:

product category

I'd like to have the gridview seperated into subheadings by category, rather than as a data field within the product gridview...

Something like:

(categories: food, clothing, shelter)

FOOD

 Rice 10s Available <buy now>

 Beans 20s Available <buy now>

 Chicken 50s Available <buy now>

CLOTHING

 Cloak 30s Available <buy now>

 Helmet 45s Available <buy now>

 Sandals 10s Available <buy now>

SHELTER

 Tent 100s Available <buy now>

Any help would be appreciated!

+1  A: 

You cannot do with the asp.net gridview out of the box.

You could use a repeater and nest a gridview inside the repeater item. Repeater for the categories. .NET 3.0 + use a ListView

You can purchase commerical controls and maybe there are some free ones which are customized to allow this behaviour.

Andrew

REA_ANDREW
Yeah I am pretty familiar with gridviews as they stand. I found this old article for data grids (the old gridview)http://www.4guysfromrolla.com/articles/072603-1.aspxHow the end result looks in that article is exactly what I want but I just don't "get" how to do a fill with a datagrid now...
A: 

You might want to look into the DevExpress grid control which not only does this but also allows the user to manually drag columns to the top to categorize in any way they see fit. You can limit which columns can be used.

I don't know if you can do this in a GridView (I don't think you can) but you can absolutely do it with the DeveExpress grid.

Mark Brittingham
A: 

A ListView will do this fairly easily, as it has grouping templates. A Repeater for the Categories, with nested GridViews for the items will also work.

If you're set on a GridView, it'll take some hackery. You can either modify the data to put in categorized rows, subclass the GridView to add new rows, add a custom control to inject markup into the GridView's HTML (I use one that closes the current row and adds a new colspanned row), or use JQuery on the client.

Subclassing is the "right" way - and can be reusable - but it's a bit of work. Modifying the data is fairly easy, but it's pretty ugly and dependent on how you're binding to the data. JQuery may actually be the easiest route here. Set the category in the 1st column, create new rows as the category changes, and then hide the 1st column. It downgrades nicely as well, since noscript will be category in 1st column. This isn't tested, but it should get you close:

var lastCategory = '';
$('TR > TD:first').each(function() {
   var thisCategory = $(this).text().trim();
   if (thisCategory != lastCategory) {
      // new category - insert subheading row
      var thisRow = $(this).parent();
      var colspan = $('> TD', thisRow).length;
      thisRow.insertBefore(
          '<tr class="subheading">' +
              '<td colspan="' + colspan.toString() + '">' +
                thisCategory +
              '</td>' +
          '</tr>'
      );
      lastCategory = thisCategory;
   }
}).hide(); // hide 1st columns
Mark Brackett
A: 

I tried to implement Mark's code, and had to adjust it slightly to get it to work. For anyone who runs across this post in the future here is the modified code:

var lastCategory = '';
$('tr').find('td:first').each(function() {
    var thisCategory = $(this).text().trim();
    if (thisCategory != lastCategory) {
        // new category - insert subheading row
        var thisRow = $(this).parent();
        var colspan = $('> td', thisRow).length;
        thisRow.before(
          '<tr class="subheading">' +
              '<td colspan="' + colspan.toString() + '">' +
                thisCategory +
              '</td>' +
          '</tr>'
        );
        lastCategory = thisCategory;
    }
}).hide();

I had to change the initial selector to get the first cell in each, and changed insertBefore() to before() as inserBefore() is used for jQuery objects not html content.

joeydi