Displaying many-to-many relation data in dataGrids

B

Bachus

Hello,
I have following problem. I have dataSet with two tables, containing data
about some people and a relation describing connections between these
people:

People:
Id
Name

Contacts:
Id
IdFriend

This is many - to - many relation, every person can have many friends and
every person can be a friend of many. I have primary key on People.Id and on
Contacts.Id, Contacts.IdFriend, and two relations:
People.Id - Contacts.Id and People.Id - Contacts.IdFriend
I want to display two dataGrids, one with list of all people, second one
with list of friends of person selected in first datagrid. Can anyone give
me some suggestion how to do that ?

Thanks,
Adam
 
G

Guest

although i have concerns on the tables design you made, but this is not your
problem now, so .. directly go to your problem :
You can bind the first grid to People table normaly , and bind the second
grid to a DataView from contacts table with filters applied to specific
person ID, and this filter should be updated when selection changed in people
grid

Code Sample:
------------------

// Say your DataSet name is "ds" and it is a member in the class

Metohd/Constructor Scope
{
// Let us bind the people grid first
peopleGrid.DataSource = ds.Tables["People"];

// To track the selected position of the selected row of people table we use
// currency manager object
CurrencyManager cm = (CurrencyManager)
this.BindingContext[ds.Tables["People"]];

// Let us subscribe to the event of changing the position
cm.PositionChanged += new EventHandler(cm_PositionChanged);

// Now, bindng the contacts grid to a special edition of the contacts table
using
// a DataView object from Contacts table to filter on the specified person ID,
contactsGrid.DataSource = ds.Tables["Contacts"].DefaultView;
// Note that you can create new DataView object instead of using DefaultView,
// but it is bad to create a new object for each user click on the people
grid!!

// Now, the DataView Filter
ds.Tables["Contacts"].DefaultView.RowFilter = "Id = " +
ds.Tables["People"].Rows[cm.Position]["Id"].ToString();

}

// The event handler to changing position, just to update the Default view
filter
private void cm_PositionChanged(object sender, EventArgs e)
{
ds.Tables["Contacts"].DefaultView.RowFilter = "Id = " +
ds.Tables["People"].Rows[cm.Position]["Id"].ToString();
}

Hope this be useful for you, good luck
 
B

Bachus

Thanks for answer, but if i understand your code example properly you
suugest to bind 1st datagrid with table People
// Let us bind the people grid first
peopleGrid.DataSource = ds.Tables["People"];
and 2nd datagrid with dataview based on Contacts table:
// a DataView object from Contacts table to filter on the specified person ID,
contactsGrid.DataSource = ds.Tables["Contacts"].DefaultView;
This is not what i want achive, that way in 1st datagird i will have Name of
persons and in 2nd datgrid only Id-s.
I want in 2nd datagrid also display names of person.
I think your code can be used to display Parent/Child relation but this can
be achived easier without using datview and filtering
if i declare DataRelation in DataSet:
// declaring relation
DataRelation dr = new DataRelation("relation",
ds.Tables["People"].Columns["Id"], ds.Tables["Contacts"].Columns["Id"]);
// adding relation to dataset
ds.Relations.Add(dr);
//binding people grid
peopleGrid.SetBinding(ds, "People");
//binding contactsgrid
contactsGrid.SetBinding(ds,"relation");
i should get the same effect.

But as i said this diplay names in first grid and only id in 2nd grid, i
tried to do that using dataView,
My idea was to declare 2 relations:
// declaring relation
DataRelation dr1 = new DataRelation("r1", ds.Tables["People"].Columns["Id"],
ds.Tables["Contacts"].Columns["Id"]);
DataRelation dr2 = new DataRelation("r2", ds.Tables["People"].Columns["Id"],
ds.Tables["Contacts"].Columns["IdFriend"]);
DataView dv = new DataView(ds.Tables["People"]);
dv.RowFilter = "Child(r2).Id = " +
ds.Tables["People"].Rows[cm.Position]["Id"].ToString();
But unfortunately Child word in RowFilter expression can be used only in
aggregat functions, because it must reference to only one row. For example:
dv.RowFilter = "Max(Child(r2).Id) = " +
ds.Tables["People"].Rows[cm.Position]["Id"].ToString();
Of course this again is not what i want to get.
I am not sure if i explained my problem correctly because i dont speak
english very good. I try to make an example with data:

Table People:
Id Name
0 person A
1 person B
2 person C
3 person D

Table Contacts:
Id IdFriend
0 1
0 2
2 1
2 3
3 1

And what i want to be displayed in datagrids:
-------------------------------
1st Datagrid
0 person A <- selected row
1 person B
2 person C
3 person D

2nd DataGrid
1 person B
2 person C
---------------------------
1st Datagrid
0 person A
1 person B <- selected row
2 person C
3 person D

2nd DataGrid
Empty
----------------------------
1st Datagrid
0 person A
1 person B
2 person C <- selected row
3 person D

2nd DataGrid
1 person B
3 person D
-----------------------------
1st Datagrid
0 person A
1 person B
2 person C
3 person D <- selected row

2nd DataGrid
1 person B
-----------------------------

Any other ideas ?

Adam

U¿ytkownik "Ahmed Ghozzy said:
although i have concerns on the tables design you made, but this is not your
problem now, so .. directly go to your problem :
You can bind the first grid to People table normaly , and bind the second
grid to a DataView from contacts table with filters applied to specific
person ID, and this filter should be updated when selection changed in people
grid

Code Sample:
------------------

// Say your DataSet name is "ds" and it is a member in the class

Metohd/Constructor Scope
{
// Let us bind the people grid first
peopleGrid.DataSource = ds.Tables["People"];

// To track the selected position of the selected row of people table we use
// currency manager object
CurrencyManager cm = (CurrencyManager)
this.BindingContext[ds.Tables["People"]];

// Let us subscribe to the event of changing the position
cm.PositionChanged += new EventHandler(cm_PositionChanged);

// Now, bindng the contacts grid to a special edition of the contacts table
using
// a DataView object from Contacts table to filter on the specified person ID,
contactsGrid.DataSource = ds.Tables["Contacts"].DefaultView;
// Note that you can create new DataView object instead of using DefaultView,
// but it is bad to create a new object for each user click on the people
grid!!

// Now, the DataView Filter
ds.Tables["Contacts"].DefaultView.RowFilter = "Id = " +
ds.Tables["People"].Rows[cm.Position]["Id"].ToString();

}

// The event handler to changing position, just to update the Default view
filter
private void cm_PositionChanged(object sender, EventArgs e)
{
ds.Tables["Contacts"].DefaultView.RowFilter = "Id = " +
ds.Tables["People"].Rows[cm.Position]["Id"].ToString();
}

Hope this be useful for you, good luck
--
Ahmed Ghozzy


Bachus said:
Hello,
I have following problem. I have dataSet with two tables, containing data
about some people and a relation describing connections between these
people:

People:
Id
Name

Contacts:
Id
IdFriend

This is many - to - many relation, every person can have many friends and
every person can be a friend of many. I have primary key on People.Id and on
Contacts.Id, Contacts.IdFriend, and two relations:
People.Id - Contacts.Id and People.Id - Contacts.IdFriend
I want to display two dataGrids, one with list of all people, second one
with list of friends of person selected in first datagrid. Can anyone give
me some suggestion how to do that ?

Thanks,
Adam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top