.NET Forum / Windows Forms / WinForm General / January 2005
DataRelations and DataGrids
|
|
Thread rating:  |
aualias - 21 Sep 2004 01:43 GMT I have tables Junk and JunkLookup in a DataSet. Junk has an integer field junkType, which is a primary key into JunkLookup.
Can I bind to Junk and use a DataRelation to display and update data in a DataGrid? Is it better to do a join in the SQL?
Ideally, I would like to copy the database relationships in the DataSet that I use on the client.
Thanks.
Alfredo
Sijin Joseph - 21 Sep 2004 04:55 GMT Hi,
Yes you can use a DataRelation for this purpose, you will need to define a DataRelation between your parent tables and child tables and then use the DataColumn.Expression property to set the value to the ParentRelations relevant field.
This is the relevant documentation from the MSDN documentation of DataColumn.Expression property
PARENT/CHILD RELATION REFERENCING
A parent table may be referenced in an expression by prepending the column name with Parent. For example, the Parent.Price references the parent table's column named Price.
A column in a child table may be referenced in an expression by prepending the column name with Child. However, because child relationships may return multiple rows, you must include the reference to the child column in an aggregate function. For example, Sum(Child.Price) would return the sum of the column named Price in the child table.
If a table has more than one child, the syntax is: Child(RelationName). For example, if a table has two child tables named Customers and Orders, and the DataRelation object is named Customers2Orders, the reference would be:
Avg(Child(Customers2Orders).Quantity)
Also check out these articles
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbts kcreatinglookuptableforlistboxorcomboboxcontrol.asp http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/ht ml/vbwlkCreatingLookupTableOnData-BoundWindowsForm.asp
Sijin Joseph http://www.indiangeek.net http://weblogs.asp.net/sjoseph
> I have tables Junk and JunkLookup in a DataSet. Junk has an integer field > junkType, which is a primary key into JunkLookup. [quoted text clipped - 9 lines] > > Alfredo aualias - 21 Sep 2004 14:53 GMT Hi Sijin,
I am still confused as to how this is used with a DataGrid. For example, if I have two tables and want to display the data (forget about editing for now):
Table1 name (char) descriptionFK (int)
Table2 - lookup id (int) description (char)
Create the DataSet with the two tables - oDataSet. Create a DataRelation LookupToMain. Call dataGrid1.SetDataBindings(oDataSet, "Table1");
How do I display the description field as a column in the DataGrid that displays data from Table1?
Are there any examples that you know of?
This cannot be difficult. I'm missing something here...
Thanks.
Alfredo
> Hi, > [quoted text clipped - 27 lines] > > Also check out these articles http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbts kcreatinglookuptableforlistboxorcomboboxcontrol.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/ht ml/vbwlkCreatingLookupTableOnData-BoundWindowsForm.asp
> Sijin Joseph > http://www.indiangeek.net [quoted text clipped - 13 lines] > > > > Alfredo "Jeffrey Tan[MSFT]" - 22 Sep 2004 06:52 GMT Hi Mike,
Based on my understanding, you want to make a Master-Details relation datatables in dataset and display them in DataGrid. Hope I did not misunderstand you.
Winform DataGrid provides good support for datarelation, what we should do is adding 2 datatables in dataset, then associate one table's primary key column with another table's foreign key column. The DataGrid will recognize the relation and show the tables in Master-Details mode.
Code like this: private void Form1_Load(object sender, System.EventArgs e) { SqlDataAdapter adapter=new SqlDataAdapter("select * from Orders", "server=localhost;database=northwind;uid=sa;pwd=test"); DataSet ds=new DataSet(); adapter.Fill(ds, "Order");
adapter=new SqlDataAdapter("select * from [Order Details]", "server=localhost;database=northwind;uid=sa;pwd=test"); adapter.Fill(ds, "Order Details");
ds.Relations.Add(new DataRelation("orderdetails", ds.Tables["Order"].Columns["OrderID"], ds.Tables["Order Details"].Columns["OrderID"]));
this.dataGrid1.DataSource=ds; }
In the code, I retrieve "Orders" and "Order Details" tables from Sql server's Northwind database, then associate the data realtion.
For more information about doing master-details databinding for DataGrid, please refer to: "Walkthrough: Creating a Master-Detail Windows Form" http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/ vbwlkwalkthroughcreatingmaster-detailwindowsform.asp
Also, the below article may help you: "Data Binding Between Controls in Windows Forms" http://msdn.microsoft.com/msdnmag/issues/02/02/cutting/default.aspx
============================================================= Thank you for your patience and cooperation. If you have any questions or concerns, please feel free to post it in the group. I am standing by to be of assistance.
Best regards, Jeffrey Tan Microsoft Online Partner Support
 Signature Get Secure! - www.microsoft.com/security This posting is provided "as is" with no warranties and confers no rights.
aualias - 22 Sep 2004 14:21 GMT Yes, that works, but it is not at all what I want. In a very simple scenario, one table is just a lookup table. (As far as I can tell, to set up the relation the lookup must be the parent or you get the following exception: "This constraint cannot be enabled as not all values have corresponding parent values." )
Furthermore, and more importantly, I do not want the Master-Details mode. I would like to display everything in one DataGrid without resorting to drill-down.
Obviously, I can do a SQL join to retrieve the data. But then I have to code the logic for an update. (I know, I am mixing the lookup scenario, where one would use a dropdown, with a straight join across the data where you would update more than one table)
I guess my basic question is: Can you use a DataGrid to display data that is contained in more than one table - without resorting to drill down (just a flat display)?
Thanks for responding.
Alfredo
> Hi Mike, > [quoted text clipped - 32 lines] > please refer to: > "Walkthrough: Creating a Master-Detail Windows Form" http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/
> vbwlkwalkthroughcreatingmaster-detailwindowsform.asp > [quoted text clipped - 12 lines] > Get Secure! - www.microsoft.com/security > This posting is provided "as is" with no warranties and confers no rights. "Jeffrey Tan[MSFT]" - 23 Sep 2004 09:56 GMT Hi Alfredo,
Thanks very much for your feedback.
Based on your statement, I think you want to display all the rows in a datagrid without master-details relations. That is: if master table's one record mapping to 3 records in child tables, then you want to join the master table with child table, and display just in one table. Then there will be some redundant master table data in the result joined table. If I misunderstand you, please feel free to point out.
Just as you said, doing this, we should use SQL statement to join this 2 tables into a result table, then fill into one datatable, and bind to DataGrid.
There is a big updating synchronization issue about this way. If we modified one record's master table column in the result datatable, the other records' master column should be updated either. To keep the updating synchronization, we should hook CurrentcyManager.ItemChanged event, update all the related records with the same key column.
Anyway, I think this is not a good design for displaying master-details database table, it has both data redundant and updating synchronization issue. Can you show me why you want to show in this way? Thanks
========================================= Thank you for your patience and cooperation. If you have any questions or concerns, please feel free to post it in the group. I am standing by to be of assistance.
Best regards, Jeffrey Tan Microsoft Online Partner Support
 Signature Get Secure! - www.microsoft.com/security This posting is provided "as is" with no warranties and confers no rights.
aualias - 23 Sep 2004 15:15 GMT Jeffrey,
Right now I am just working out possible scenarios for a project, so I have probably not been as specific as I should have been. I think that you have answered my question. You cannot use a DataRelation between two tables in a DataSet in this manner. That's fine, now I don't have to figure out how to do it...
As to the SQL. I would just have one table (the join) in the DataSet and update the database from the data in that table. There would not be any redundant data and I would have to write some code for the update.
To be honest, while the default master-details display is kind of neat, I find it totally useless. It is not the way a typical user is used to viewing data. In this case I just want to show a useful subset of the data, which is a very typical thing to do. I do not want to show all the data in the tables.
It would be great if I could create two tables and a relation, then display and update data in a flat display using DataGrid. Since the DataGrid uses a table DataMember for each display, it seems that I have to use a join to get the fields of interest to show together.
Thanks for your help.
Alfredo
> Hi Alfredo, > [quoted text clipped - 31 lines] > Get Secure! - www.microsoft.com/security > This posting is provided "as is" with no warranties and confers no rights. "Jeffrey Tan[MSFT]" - 24 Sep 2004 04:45 GMT Hi Alfredo,
Thanks very much for your feedback.
Yes, for your requirement of displaying both the parent and child rows in one table, there is no build-in support for the updating synchroniztion, we have to do it in code manually.
Maybe we may refer to another design to workaround this issue:
I think your concern is displaying the all the child table's rows. We may just select the parent and child tables in 2 datatables in one dataset, add the datarelation. Then we may only display the child table in the main DataGrid, then use the datarelation to display the selected child row's parent row in another datagrid(or in several TextBox, as you like). Because several child rows share the one parent row, this will be enough for the customer to view them. Also, the only one parent row will eliminate the parent row updating synchronization issue.
Also, we need to hook main DataGrid's currentcell change event to change the parent datagrid's dispaly, keep the display synchronization. Also, we may select all the child rows in the code to enable the user to view the parent/child relation, sample code like this:
DataSet ds=null; private void Form3_Load(object sender, System.EventArgs e) { SqlDataAdapter adapter=new SqlDataAdapter("select * from Orders", "server=localhost;database=northwind;uid=sa;pwd=test"); ds=new DataSet(); adapter.Fill(ds, "Order");
adapter=new SqlDataAdapter("select * from [Order Details]", "server=localhost;database=northwind;uid=sa;pwd=test"); adapter.Fill(ds, "Order Details");
ds.Relations.Add(new DataRelation("orderdetails", ds.Tables["Order"].Columns["OrderID"], ds.Tables["Order Details"].Columns["OrderID"]));
this.dataGrid1.DataSource=ds.Tables["Order Details"]; Bind_parentGrid(); }
private void dataGrid1_CurrentCellChanged(object sender, System.EventArgs e) { Bind_parentGrid(); }
private void Bind_parentGrid() { CurrencyManager cm=this.BindingContext[ds.Tables["Order Details"]] as CurrencyManager; DataView dv=cm.List as DataView; DataRow dr=dv[this.dataGrid1.CurrentCell.RowNumber].Row.GetParentRow("orderdetails") ;
ds.Tables["Order"].DefaultView.RowFilter="OrderID="+dr["OrderID"].ToString() ; this.dataGrid2.DataSource=ds.Tables["Order"].DefaultView;
if(dr!=null) { DataRow[] child_rows=dr.GetChildRows("orderdetails"); for(int i=0;i<dv.Count;i++) { foreach(DataRow row in child_rows) { if(dv[i].Row.Equals(row)) { this.dataGrid1.Select(i); } } } } } It works well on my side.
Anyway, this is only a design option for your information.
Thank you for your patience and cooperation. If you have any questions or concerns, please feel free to post it in the group. I am standing by to be of assistance.
Best regards, Jeffrey Tan Microsoft Online Partner Support
 Signature Get Secure! - www.microsoft.com/security This posting is provided "as is" with no warranties and confers no rights.
aualias - 24 Sep 2004 13:49 GMT Jeffrey,
Thanks for bearing with me.
My question was about using one DataGrid and displaying data from more than one related table. I believe I have the answer to that now.
Your example is basically how I would do it if I were using two DataGrids. That would be a good solution in many circumstances. In the app that I am thinking about, all the necessary fields would easily fit in one grid display without the user having to scroll horizontally. In this case, showing everything in one grid is a much cleaner UI.
Thanks again.
Alfredo
> Hi Alfredo, > [quoted text clipped - 52 lines] > DataView dv=cm.List as DataView; > DataRow dr=dv[this.dataGrid1.CurrentCell.RowNumber].Row.GetParentRow("orderdetails")
> ; ds.Tables["Order"].DefaultView.RowFilter="OrderID="+dr["OrderID"].ToString()
> ; > this.dataGrid2.DataSource=ds.Tables["Order"].DefaultView; [quoted text clipped - 28 lines] > Get Secure! - www.microsoft.com/security > This posting is provided "as is" with no warranties and confers no rights. "Jeffrey Tan[MSFT]" - 27 Sep 2004 06:33 GMT Hi Alfredo,
Thanks very much for your feedback.
I think this is totally a design issue, and we have several choice, and we have to make decision. Anyway, I am glad you have got what you want, if you need further help, please feel free to tell me, Thanks.
Best regards, Jeffrey Tan Microsoft Online Partner Support
 Signature Get Secure! - www.microsoft.com/security This posting is provided "as is" with no warranties and confers no rights.
cyourch - 20 Jan 2005 21:19 GMT I had the same question that 'aualias' asked but it appears that it was never answered in this thread. So, how would you use one datagrid to display 'Table1' below but instead of showing the 'TagTypeID' column from 'Table1' I want show the 'TagTypeName' column from 'Table2' instead?
Here are the 2 tables: Table1 --> TagID, TagName, TagTypeID Table2 --> TagTypeID, TagTypeName
> Hi Alfredo, > [quoted text clipped - 9 lines] > Get Secure! - www.microsoft.com/security > This posting is provided "as is" with no warranties and confers no rights.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|