I had a task to bind two DataGridView's, main problem I can't see the changes when I cast BindingSource data source to DataSet (I need this for SqlDataAdapter).
I can workaround this by deleting db table contents, but this is not suitable for me.
I could catch these events, but I need to update DB on disposing the Form.
var bs = (BindingSource)dataGridView1.DataSource;
var set = (DataSet)bs.DataSource; //here DataSet HasChanges() method always returns true
And when I use Tables from DataSet in SqlDataAdapter Update() and Fill() methods do the Insert for me, because values are always shown as new.
It is kind of though to explain it right, I hope I have succeeded.
Thanks.
EDIT
Fixed it by initializing DataSet on class level and adding AcceptChanges method.
Also removed casting from BindingSource.
Code snippet for initialization of DataSet:
dataSetT = new DataSet();
dataSetT.ReadXmlSchema(xmlSchemeFile);
dataSetT.ReadXml(populateDataSet == null ? xmlSchemeFile : xmlDataFile, XmlReadMode.IgnoreSchema);
var autoSource = new BindingSource();
var repairSource = new BindingSource();
autoSource.DataSource = dataSetT;
autoSource.DataMember = "Auto";
repairSource.DataSource = autoSource;
repairSource.DataMember = "VIN_FK";
dataGridView1.AutoGenerateColumns = true;
dataGridView2.AutoGenerateColumns = true;
dataGridView1.DataSource = autoSource;
dataGridView2.DataSource = repairSource;
dataSetT.AcceptChanges();
With AcceptChanges method now dataSetT.HasChanges() returns a realistic value. And then I use DataAdapter Update method.
Case closed.
I have found answer to my question, description is in edited question.
Thanks.
Related
I can't figure out why I am getting a "DataTable already belongs to another DataSet" exception.
Here is my code:
DataSet AlertSet = new DataSet();
DataTable generalAlertData = new DataTable("GeneralAlertData");
generalAlertData = //function that returns datatable
//throws exception
AlertSet.Tables.Add(generalAlertData)
When is another dataset being created and when is the generalAlertData datatable being added to it?
I tried using a slightly different syntax to create and add the table and got the same error:
DataSet AlertSet = new DataSet();
DataTable generalAlertData = //function that returns datatable
//throws exception
AlertSet .Tables.Add(generalAlertData);
It depends on what your function that retrieve the datatable does.
If that function use a DataAdapter and fills a dataset then you have the DataSet property of the table automatically assigned and you need to remove it before assigning a different DataSet
You could try this to remove the original DataSet and use your own
DataTable generalAlertData = GetTable();
DataSet u = generalAlertData.DataSet;
u.Tables.Remove(generalAlertData.TableName);
AlertSet.Tables.Add(generalAlertData);
So, if your hypothetical GetTable works in this way
public DataTable GetTable()
{
...
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
return ds.Tables[0];
}
then you have the DataSet assigned to the returned datatable.
Instead this code doesn't assign anything to the DataSet property
public DataTable GetTable()
{
...
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
The DataTable returned from the method call, was added to a DataSet. Make sure it's not added to a DataSet; just build a stand alone DataTable.
As a side-note, returning a DataTable from a method call that assigns to this one makes the line above it irrelevant (the new).
This is an old question now but maybe this answer will help others.
I too received this error. I looked through my source code, found literally no other datasets and was puzzled as to why this was happening.
The solution to my issue was in my data access library. It didn't have a "getDataTable" routine but I did have a getDataset routine. When I needed just a datatable I called getDataset and took the tables(0) datatable instance.
The end result of this is that I got back my datatable like I wanted, but the datatable was already part of the dataset returned from my data access call. Thus, the error.
I had to add a getDatatable routine into my data access library to eliminate this problem.
I had the same problem and I solved it using Remove. In my opinion, your code could be this:
DataSet AlertSet = new DataSet();
DataTable generalAlertData = new DataTable("GeneralAlertData");
AlertSet.Tables.Add(generalAlertData);
AlertSet.Tables.Remove(generalAlertData);
Please, let me know if this code works.
My working code was like this:
DataTable myTable = new DataTable();
private void Save()
{
DataSet myDataSet = new DataSet();
myDataSet.Tables.Add(myTable);
myDataSet.Tables.Remove(myTable);//This works
myDataSet.WriteXml("myTable.xml");
}
private void buttonSave_Click(object sender, EventArgs e)
{
Save();
}
Every time I clicked the button buttonSave, the message “DataTable already belongs to another DataSet" appeared. After writing the line code myDataSet.Tables.Remove(myTable);//This works the application started running without problems and now I can click the button more times, without losing the value of myTable and without the error message.
I hope this can help.
I am using Winforms DevExpress and I am binding a DataTable to a DataGridView which is working fine. The problem I am having is that I have some functions that will build a new DataTable object which is separate from the original which needs to replace the original DataTable that is bound to the DataGridView.
DataTable originalTable = new DataTable("OriginalTable");
//Populate originalTable
myDataGridControl.DataSource = originalTable;
Everything works fine with the code above, but the following code creates a new DataTable and needs to be set as the DataSource for myDataGridControl.
DataTable newTable = new DataTable("NewTable");
//Populate newTable
//Set newTable as the DataSource for myDataGridControl
myDataGridControl.DataSource = newTable;
I have tried several different attempts to make this work such as calling RefreshDataSource(), Refresh(), setting DataSource to null. I have not gotten it to work yet. How do I do this?
Try using a BindingSource, like this:
DataTable sourceTable = new DataTable("OriginalTable");
BindingSource source = new BindingSource();
source.DataSource = sourceTable;
myDataGridControl.Datasource = source;
Now when you want to re-bind, update the sourceTable variable, like this:
sourceTable = new DataTable("NewTable");
// If the structure of `OriginalTable` and `NewTable` are the same, then do this:
source.ResetBindings(false);
// If the structure of `OriginalTable` and `NewTable` are different, then do this:
source.ResetBindinds(true);
Note: Read BindingSource.ResetBindings Method for more information about ResetBindings().
Having you tried the following combination?:
myDataGridControl.DataSource = originalTable;
myDataGridControl.DataSource = null;
myDataGridControl.DataSource = newTable;
In my experience, setting the DataSource to null then to the second source does the trick.
In case anybody is having trouble even after trying the other suggestions, the following call to PopulateColumns() on the GridControl.MainView property solved the problem for me.
For example:
myDataGridControl.MainView.PopulateColumns();
This can also be referenced from the following article with DevExpress. http://www.devexpress.com/Support/Center/Question/Details/Q362978
Kinda old topic, but since it bugged me, I decided to share my experience...
Binding the source didn't work for me and Datagridview doesn't have "MainView" variable.
I suspect the issue happens, in my case, after running the sorting command:
MyDataTable.DefaultView.Sort = "Column Asc";
MyDataTable = MyDataTable.DefaultView.ToTable();
My solution was to rebind again after actions performed:
myDataGrid.DataSource = MyDataTable;
I'm trying to set the dataGridView as a datasource of some other datagridview, but it is not working. Please help me.
this.dataGridView2.DataSource = this.dataGridView1;
No compiler error, but not working as well.
this.dataGridView2.DataSource = this.dataGridView1;
this will show no compile error because this.dataGridView2.DataSource is expecting a type of object and you are assigning an object to it, but no datasource assigned here , to do that
this.dataGridView2.DataSource = this.dataGridView1.DataSource
assign like this
to Solve the Problem of changing data in datagrid one while changing data on first one
Try this
DataTable dt = (DataTable)dataGridView1.DataSource;
dataGridView2.DataSource = dt.Copy();
#Nighil sounds close, I don't know if that worked for you but I would not recomend using dataGridView as a datasource, I suggest you should separate out the logic keeping data separate from user controls, also using a 'BindingSource' gives you one easy method for refreshing data;
Say we had a method called 'getTablefromDatasource()' which got the data to be displayed and returned a 'DataTable'
DataTable table = getTablefromDatasource();
BindingSource source = new BindingSource();
dataGridView1.DataSource = source;
dataGridView2.DataSource = source;
then you can refresh the data with:
source.ResetBindings(false);
Following Error in this line.
datagridview1.Rows.Clear()
but this line gives error:
Cannot clear this list.
I also had similiar problem when I try to clear DataSource of a DataGridView after I had binded it to a DataTable with:
DataTable DT = ... ; // fill it
datagridview1.DataSource = DT;
when I try to clear it's rows later with the following code:
datagridview1.DataSource = null
I get this error:
ERROR: Object reference not set to an instance of an object
This object reference ERROR problem already solved in here. But I managed to solve my own problem (clearing DataGridView rows) with this code:
DataTable DT = (DataTable)datagridview1.DataSource;
if (DT != null)
DT.Clear();
I know that this question was asked a very long time ago, but I hope my solution would solve someone problems.
Is your DataGridView bound to a DataSource, i think thats why its not allowing you to clear it since its bound to an underlying DataTable or List.
you could try setting the DataSource Property to null
datagridview1.DataSource = null; for clearing
private void button_Limpar_Click(object sender, EventArgs e)
{
DataTable DT = (DataTable)dataGridView_Cidade.DataSource;
if (DT != null)
DT.Clear();
}
#endregion
Simply add this line at beginning of your event:
dgv_nameOfGridView.DataSource=false;
Now every time you click it will erase the dgv..
You have to Clear datasource not datagridview rows.
datagridview1.DataSource = null;
Another way is
1) Dont assign direct datasource to gridview.
add rows from datatable to gridview
foreach (DataRow row in dataTable.Rows)
{
var dataGridRow = new DataGridViewRow();
dataGridRow.CreateCells(datagridview1);
for (int i = 0; i < row.ItemArray.Length; i++)
{
dataGridRow.Cells[i].Value = row.ItemArray[i];
}
datagridview1.Rows.Add(dataGridRow);
}
then use
datagridview1.Rows.Clear()
You can use this simple method:
First clear your DataTable and then refresh your DataGridView
dataTable.Clear();
dataGridView.Refresh();
Hope this help
Easy solution is to clear the DataSet.
ds.Clear();
Since you are using a bound grid, have you tried to call your loading
function twice and verified that the data is not doubling?
Since it is bound, loading twice ought to not duplicate the data.
http://www.vbforums.com/showpost.php?s=aa5f116586c00a2d9ea15e3727fc5c2f&p=2841192&postcount=9
First clear DataSource and then clear DataGridView
in VB
datagridview1.DataSource = Nothing
datagridview1.Rows.Clear()
hope help
If you load your DataGridView with a parameter, you can send an empty parameter to it. This will clear your DataGridView without having to set its DataSet to null.
For example, I load my DataGridView with a Code, when I fill a TextBox.
this.dataTable1TableAdapter.Fill(this.ds_MyDataSet.DataTable1, TextBox1.Text);
If I want to clear its content, then
this.dataTable1TableAdapter.Fill(this.ds_MyDataSet.DataTable1, "");
Here we are 8 years later.
Although
datagridview1.DataSource = null;
is a satisfactory answer for most, for me this removes all customizations I've added to the columns in design view. So hidden columns appears if I want to clear out the rows.
So rather than clear out rows:
datagridview1.Rows.Clear()
Clear out the DataTable or DataView that you used to set up the DataGridView. Note you don't have to check if something is null nor worry about Object not set to reference errors.
So here's how I did mine:
//Populate the datagridview
DataTable _DT = new DataTable();
BindingSource _BS = new BindingSource();
//Initially fill up your datatable with stuff
//You can call this method again if data needed to be changed
public void fillDT(int id) {
_DT = fillUpDataTableWithStuffFromDB(id);
_BS.DataSource = _DT.DefaultView;
datagridview1.DataSource = _BS;
_BS.ResetBindings(false);
}
//You can use this method to mimic the functionality above
//But rather fetching data, just clear out the datatable and pass it in
public void clearDT() {
_DT.Clear();
datagridview1.DataSource = _DT.DefaultView;
datagridview1.Refresh();
}
As you can see above, I just cleared out the datatable, and passed that into the datagrid. This kept all my properties I set on the datagridview column.
foreach (DataGridViewRow item in this.datagridview.Rows)
{
datagridview.Rows.RemoveAt(item.Index);
}
I had the same problem I tried with many solutions.
In the end I realized that we can't clear the DataGridView if we use it's property "DGV.Datasource" because DGV takes its data from the dataset so you need to clear the DataTable rows
Dataset.Tables["TableName"].Rows.Clear();
If you use this function in the Load of the Form you need to add a condition
if (DataSet.Tables["TableName"] !=null)
Dataset.Tables["TableName"].Rows.Clear();
or you will get this error
Object reference not set to an instance of an object.
I am trying to remove all the rows to reload them (I need to remove all rows) For some reason its not removing them from my datagridview (tho its not adding any extra either) nothing is happening. I have tried many different methods, I know I have done this in the past. (maybe because its end of the day)
Here is my code trying a whole bunch of removes
private void loadMSXGridView()
{
BindingSource bs = new BindingSource();
dgv.DataSource = null;
dgv.Refresh();
bs.DataSource = GetTable();
dgv.DataSource = bs;
dgv.Columns[0].Width = 391;
dgv.Columns[1].Width = 30;
}
private DataTable GetTable()
{
DataTable t = new DataTable();
t.Rows.Clear();
t.AcceptChanges();
t.Columns.Add("Accounting Line", typeof(string));
t.Columns.Add("#", typeof(string));
foreach (AMAPnr.RemarkElement re in AMAPnr._RemarkElements)
{
if (re.ElementID == "RM" && re.FreeFlow.StartsWith("*MS"))
{
DataGridViewCell gridCellText;
DataGridViewCell gridCellElement;
gridCellText = new DataGridViewTextBoxCell();
gridCellText.Value = re.FreeFlow;
gridCellElement = new DataGridViewTextBoxCell();
gridCellElement.Value = re.ElementNo.ToString();
t.Rows.Add(gridCellText.Value, gridCellElement.Value);
}
}
return t;
}
My delete button calls loadMSXGridView, I only need to refresh everything because the items in my datagridview are associated to an element number, which won't remain the same
Initially, you are data-binding:
dgv.DataSource = GetTable();
you should then continue data-binding; either tell the table to clear itself (and repopulate the data), or just assign a different data-table to dgv.DataSource.
In my limited data binding experience it is not easy to edit a data source. You should handle your data edits using one of the row binding or other events. However if you want to edit a datasource you basically have to clone the structure, then import the rows. So in this sense you should actually go back to your datasource and select exactly what you want.
However..
If you want to filter / edit your data here is how you can do it:
DataSet ds1 = [Your Data Source]
DataSet ds2 = new DataSet();
ds2 = ds1.Clone();
for (int i = 0; i < ds1.Tables[0].Rows.Count; i++)
{
if (ds1.Tables[0].Rows[i].ItemArray[0].ToString() != "SomeValue")
{
ds2.Tables[0].ImportRow(ds1.Tables[0].Rows[i]);
}
}
ds1 = ds2;
If you simply just want to add a different datatable as the datasource, then do:
datagridview.DataSource = datatable;
datagridview.Invalidate();
That should work, as I have just done the exact same thing on a project i'm working on at the minute :)
My fault, everything worked after running a throughough debug I found
The remarks elements were not being deleted, thus it was getting deleted by adding the same items back in. I remove the items from the RemarkElement section and it works, thanks for your help everyone!
I would suggest to set the DataSource of your DataGridView to a BindingSource and change the DataSource of the BindingSource instead:
var table1 = GetDataTable();
var bindingSource1 = new BindingSource(table1, null);
dataGridView1.DataSource = bindingSource1;
// after reload
var table2 = GetDataTable();
bindingSource1.DataSource = table2;
that solves most problems, since you don't have to worry about how your data is bound.