views:

3481

answers:

6

Hi All,

I have a List of custom object, which consist of a custom list.

class person{
  string name;
  int age;
  List<friend> allMyFriends;
}

class friend{
  string name;
  string address;
}

I'trying to bind a list of these objects to a GridView and the Grid should create for each friend a column and write the name in it. If some people have the same frined the grid shouldn't create a seperate column, but use the existing one. You know what I mean. (The classes are just some sample classes to simplify my case)

Is there a way to dynamically customize the binding?

I can change the class definitions and so on, if they need to inherit from some interfaces or so on.

I googled a lot, but no example really seemed to cover this case.

Could the use of a objectSourceControl solve my problem in some way?

I really appreciate your help, Cheers, derSteve

A: 

Have a look at my answer to a similar 'nested binding' question here.

flesh
+1  A: 

It sounds like you are trying to display a matrix / crosstab in GridView. You might find it easier to grab your retrieve your data in a format more compatible to this. You could consider writing a crosstab query if you are using SQL server.

If you must work with the objects in their current form, Creating a merged list of friends before starting could also help by providing the column list. You could then bind to each column to a function call which could attempt to find the column person in the rows friend list.

Not beautiful, but could work...

HectorMac
A: 

Thanks for your comments, but I need to preserve the structure of the data and actually the structure is quite appropriate for my solution.

To give some more information: In the end I have a list of persons, while each person in the list has a list of friends.

List<person> allPerson = new List<person>();
// fill the list
Grid.DataSource = allPerson;
Grid.DataBind()

The table should have columns for each friend and the rows are the person. Where a person has a friend a cross (or whatever) needs to be placed in the grid.

friend1 friend2
   x              peter
   x       x      adam

At the moment a intercept the RowDataBound event and since the binding only creates the rows with the names and not the columns, because the only property on my person object is the name. Is there a way to force the binding to look through the List Property in the person objects and create a column for each of them.

Thanks in advance, Steve

derSteve
A: 

use the following :

DataBinder.Eval(Container.DataItem,"PPP.PPP")

A: 

You could also just use the RowDataBound event handler to do complex bindings.

sujata
A: 

I was able to solve this using a DataTable as your datasource for the Grid. I don't like the idea of moving from a nice clean object to a DataTable, but it provides support for the dynamic binding you need. I modified your friend object to have a few constructors. This allowed me to cleanup the static code declaration but might not be necessary in your implmentation.

The basic idea is that you will step through all possible friends, add their name as a DataColumn in a DataTable, then fill in the data for all person objects and their respective friends. This could probably be written to work in a single iteration of the allPerson object but I preferred two iterations to make the code easier to read.

The solution is written for c# 3.5 but could be converted for older versions by changing the static data declaration. I hope this helps.

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // setup your person object with static data for testing
        List<person> allPerson = new List<person>()
        {
            new person() 
            { 
                name = "Dan", 
                age = 21, 
                allMyFriends = new List<friend>() { new friend("James"), new friend("John"), new friend("Matt") } 
            }, 
            new person() 
            { 
                name = "James", 
                age = 21, 
                allMyFriends = new List<friend>() { new friend("Dan"), new friend("Matt"), new friend("Tom") } 
            }, 
            new person() 
            { 
                name = "John", 
                age = 21, 
                allMyFriends = new List<friend>() { new friend("Dan") } 
            }, 
            new person() 
            { 
                name = "Matt", 
                age = 21, 
                allMyFriends = new List<friend>() { new friend("Dan"), new friend("James") } 
            }, 
            new person() 
            { 
                name = "Tom", 
                age = 21, 
                allMyFriends = new List<friend>() { new friend("James") } 
            }
        };

        System.Data.DataTable dt = new System.Data.DataTable();
        dt.Columns.Add("Name");
        dt.Columns.Add("Age");

        foreach (person p in allPerson)
        {
            // step through each person and look at their friends
            foreach (friend f in p.allMyFriends)
            {
                // look to see if this friend has a column already
                if (!dt.Columns.Contains(f.name))
                {
                    dt.Columns.Add(f.name);
                }
            }
        }

        foreach (person p in allPerson)
        {
            // create the datarow that represents the person
            System.Data.DataRow dr = dt.NewRow();
            dr["Name"] = p.name;
            dr["Age"] = p.age;

            // find the friends and mark them
            foreach (friend f in p.allMyFriends)
            {
                dr[f.name] = "X";
            }

            dt.Rows.Add(dr);
        }

        // fill the list
        this.Grid.DataSource = dt;
        this.Grid.DataBind();

    }
}

public class person
{
    public string name;
    public int age;
    public List<friend> allMyFriends = new List<friend>();
}

public class friend
{
    public string name;
    public string address;

    public friend()
    {

    }

    public friend(string name)
    {
        this.name = name;
    }

    public friend(string name, string address)
    {
        this.name = name;
        this.address = address;
    }
}

Edit: I forgot to add how this is rendered.

-------------------------------------------------
| Name  | Age | James | John | Matt | Dan | Tom |
-------------------------------------------------
| Dan   | 21  | X     | X    | X    |     |     |
| James | 21  |       |      | X    | X   | X   |
| John  | 21  |       |      |      | X   |     |
| Matt  | 21  | X     |      |      | X   |     |
| Tom   | 21  | X     |      |      |     |     |
-------------------------------------------------   
Chris Porter