I created a very simple test to boil this issue down to common elements. I have an MS Access DB with 1 and only 1 table in it. 2 columns (ID, Name) and added 4 rows of data to the table. Here is the steps to reproduce the problem:
I added a DataSet containing a DataTable to datasources of my project. (Add new datasource from database)
I added a test Form1 with 1 and only 1 control, a DataGridView
Using designer I bound that grid to the table in the datasources of project. (Using DataSource property of DataGridView at design-time).
My Form_Load looks like this:
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'testDBDataSet.TestTable' table. You can move, or remove it, as needed.
this.testTableTableAdapter.Fill(this.testDBDataSet.TestTable);
BindingSource bs = (BindingSource)dgvTestData.DataSource;
DataTable dt = (dgvTestData.DataSource) as DataTable;
}
When I step past the last line of code, dt is null. What am I missing?
I know it is something simple and probably obvious, but I don't see it. If I just run the code back to the form, the DataGridView has data in it.
What am I doing wrong? How can I get the underlying DataTable from BindingSource which is set as DataSource of my DataGridView using above steps?
What am I doing wrong?
When dgvTestData.DataSource is BindingSource you can not expect dgvTestData.DataSource as DataTable return anything else than null.
The as operator is like a cast operation. However, if the conversion isn't possible, as returns null instead of raising an exception.
How can I get the underlying DataTable from BindingSource?
It seems you bound the grid to a binding source which its DataSource is set to a DataSet and its DataMember is name of a DataTable. It's the default behavior when you set data source of grid to a table using designer or drag a Table from Data Sources Window and drop on your form. So if you are following default scenarios, you can use such code to get the DataTable:
BindingSource bs = (BindingSource)dgvTestData.DataSource;
var dt = (bs.DataSource as DataSet).Tables[bs.DataMember];
If you are using any other scenario different than the default scenario, you can simply use DataSource and DataMember properties of your binding sources to extract the DataTable which is using for data-binding.
Is there a better way?
It depends, why not simply use:
var dt = this.testDBDataSet.TestTable;
Related
I am creating a DataTable to store information for my project, which will later push information into a MS Excel file. I want to show the user some of this data in my WinForms project through a DataGridView control, but I do not want to show the user the entire DataTable - just essential columns. I've found this to be a challenge since DataTable is set up to work with rows more than columns.
I've tried to copy across from one DataTable to another, using one for storage and a subset for display, but due to columns sharing references, I either can't have multiple columns with the same name, or I alter the columns in one DataTable which subsequently changes both. I've also tried creating a subset table with DataView, but had the same problems.
Is there a clean way to go about this?
(Otherwise I'll just do it rough and try to set my column sizes so that unnecessary data can't be seen in the DataGridView.)
You need to add the columns (you want to show) in designer view. And set the property AutoGenerateColumns to false
Try this
To hide Columns...
this.DataGridView.Columns[0].Visible = false;
or you could filter the data from one datatable into another...
string[] colnames = new string[] { "col1", "col2" };
dt2 = dt1.DefaultView.ToTable(false, colnames);
I've not tested any of that code....
You could just fill another DataTable selecting only the Columns that you want from you data source....
I have a DataGridView that I populate by binding it to a DataTable returned from an sql query, which works as you'd expect.
Later on if a user wants to see additional information in the DataGridView by clicking a button I manually add a column to the end of the DataGridView - dgvOrders.Columns.Add("profit", "Profit"); and populate it with data based on logic determined by other DataGridColumns cells values.
It all works perfectly until you click one of the column headers to sort the data, at which point the data is sorted correctly BUT every cell in my new column loses it's value and shows as empty. On top of that I don't seem to be able to filter by my new column at all either. Is it a no-no to manually add columns to a databound DataGridView or am I missing something else here?
Firstly, I would urge you to share your code, its much easier to look than guessing.. Sounds like your problem is with the data binding. Personally I don't like working directly with the data grid. Its much easier to work on your model or adapter and then rebind:
..your model container or adapter, e.g. SqlDataAdapter gets updated here...
DataTable dt = new DataTable();
adapter.Fill(dt);
dgvOrders.DataSource = dt;
dgvOrders.Columns.Add("yourcolumn", "yourcolumn");
otherwise if you prefer to work directly on the dgvOrders, do something like that:
dgvOrders.Columns.Add(new BoundField { DataField = "yourcolumn"})
dgvOrders.DataSource = yourdatasource;
dgvOrders.DataBind(); //dont forget to databind again!
just having some small issues with c# winforms datagridview. Here's my scenario
I am using entity framework and am trying to bind certain entity models to my datagridview datasource.
var query = from q in context.foo
select q;
dgv_Disp.DataSource = query.ToList();
When I ran this piece of code above on a form class which had a datagridview in the GUI, it all worked fine. The datagridview will automatically generate columns and the number of rows.
But when I run this exact same code with the exception that I don't have a datagridview in the GUI, I just declare it programmatically and then set the datasource like the above code. And when I do it this way, no rows or columns are generated.
What is the difference between these two different datagridviews? I know that there are properties set in the designer.cs file of the form class. But I tried copying these settings and it still won't populate.
I know it's probably something simple but I just can't figure this out at all. If someone could show me what im doing wrong, that'd be great!
Edit
I have used AutoGenerateColumns = true but it didn't make any difference. Also I'm not actually trying to display this datagridview, I was just binding it to entity objects that way I could access its members using a string index. But I dont want to query the database just to get my info in a datagridview specific format because in my actual scenario, I already have my entity data from a previous query. I was just using the above code as an example.
Your code should be work. below is sample code to bind List<T> to DataGridView , but you need to add the DataGridView to the form or some other panel ( or container)
public Form1()
{
InitializeComponent();
DataGridView gv = new DataGridView();
gv.DataSource = new List<string>() { "sss", "aaa" }.Select(x => new { Name = x }).ToList();
this.Controls.Add(gv); // add gridview to current form or panel ( or container), then only it will display
}
At first there is no grid in my design. Iam adding grid also in dynamically
AmolEntities db=new AmolEntities();
DataGrid dataGridView1 = new DataGrid();
this.Controls.Add(dataGridView1);
var v= from n in db.oe_subjects select n;
dataGridView1.DataSource = v.ToList();
When creating object of datagridview you need to set
dataGridView1.AutoGenerateColumns = true
Please make sure you have done this before assigning datasource to it.
Winforms datagridview only generates columns if its actually part of the GUI. By sticking all of my datagridviews on the form in the form designer, the datagridviews generated the columns as I needed. I didn't actually need the form so I just didn't call the show() method. Seems like a bit of a hackish way of dealing with the issue but that's how I fixed this
I have done easily First declared a new variable of the same DataTable and then I put tableAdapter.Fill(dt); and then dbGrid.DataSource = dt;
And it worked fine
When I change DataSource of my DataGridView with DataTable who don't have rows, and after that change DataSource with DataTable who contains rows, header text changes and another properties like width...
Try using a BindingSource control between the DataGridView and the DataTable. The BindingSource control has a very useful property called Filter that will filter out unwanted rows without creating a new DataTable object or otherwise affecting the structure of the underlying DataTable, thus your DataGridView's headers will not be affected.
You can either do this manually through code or drop an instance of the BindingSource in the designer. The code would look something like this:
BindingSource bs = new BindingSource();
bs.DataSource = YourDataTable;
YourGridView.DataSource = bs;
Then you can filter out your results by simply doing:
bs.Filter = "some_column = 'some_value'";
Try clearing your DGV first before re-populating it with a DataTable that has rows.
I solve the problem by making copy of DT and clearing rows from her. Than I assign that DT to DataSorce and now all works fine. Maybe not best way but it works. Thank you all!
I have used full join to populate my datagridview with the contents of two tables, now I want to save the contents of the datagridview into a single table.
I don't want to use loops and I don't wanna access single cells of the datagridview.
Now anyone has a solution for this ?
and using datasource of the datagridview and its adapter is not the solution,so please reply honestly after understanding my problem.
How about using your full join to populate the Third Table, then bind the third table to the DataGridView, therefor when you make changes to the DataGridView the third table is updated automatically
try this. I created a new winforms project, i added a button and a datgridview. I created a public datatable and gave it columns and a row in the Form1 constructor. When you click the button it displays the number of rows contained in the datatable. So I run the program click the button MessageBox says 1 I add a row to the datagrid view and click the button Messagebox says 2
//public/Global datatable
public DataTable myTable = new DataTable();
public Form1()
{
InitializeComponent();
//create myTable Columns
myTable.Columns.Add("Name");
myTable.Columns.Add("Age");
myTable.Columns.Add("Number");
//add one row
myTable.Rows.Add(new object[] {"myName","myAge","myNumber"});
bind to the datagridview
dataGridView1.DataSource = myTable;
}
private void button1_Click(object sender, EventArgs e)
{
//display the number or rows in the datatable
MessageBox.Show(myTable.Rows.Count.ToString());
}
}
I'm not sure I understand what you're asking for, but I will attempt to be of service. You are obtaining a result set that combines two tables using a full join, and then want to output that result set into a third table? Is that correct?
First, I would recommend creating a view for this third table. That is probably the most efficient and dynamic solution. If you want to present that data to your users, have the datagrid bind to the view. If you made any changes to the two original tables, you would have to update the third "by hand". A view does this automatically.