Sorry for my bad English, hope you can understand my situation.
A table in database will be shown in TextBoxs from a Form with DataBinding, like the following:
DataTable dataTable = dataBase.ReadTable(tableName); //Suppose: dataTable.Rows.Count == 10
BindingManagerBase bindingManager = BindingContext[dataTable];
BindTextBoxsWith(dataTable);
ActionToChange(bindingManager.Position);
Everthing works fine. Then I need to add a new row and switch to the new row for editing, so these code are added:
DataRow dataRow = dataTable.NewRow();
dataRow[primaryKey] = 0;
dataTable.Add(dataRow);
bindingManager.Position = dataTable.Rows.Count - 1; //value in breakpoint: dataTable.Rows.Count == 11, bindingManager.Position == 0
As shown in the comment, the BindingManager's Position don't work in a normal style. How can it be?
Then I try these code:
dataTable = dataTable.Copy();
BindTextBoxsAgainWith(dataTable);
bindingManager = BindingContext[dataTable];
Now bindingManager.Position can work, but the problem is when bindingManager.Position changes, a same row is bound everytime.
What caused this problem? Expect your help.
Related
I have DataGridView with a Column named flag and others.
When I apply a filter:
dataGridView2.DataSource =
new DataView(ds, "flag = 1", "tw_Name DESC", DataViewRowState.CurrentRows);
it shows only Rows where he Column flag value is equal to 1, but...
when I try to programmatically change this value, for example in 6 checked rows:
foreach (DataGridViewRow row in dataGridView2.Rows)
{
if (Convert.ToBoolean(row.Cells["zazn"].Value))
{
row.Cells["flags"].Value = 0;
}
}
three Rows disappear, one Row changes its value, two Rows do not change.
Next, when I click any Row, I get only 2 of the desired changes.
Since you're working with a DataTable, it's preferable that you modify the values of its Rows' content instead the DataGridView Cells while a Filter is active on the DataTable's DataView.
This causes the immediate propagation of the data changes, which your DataGridView will acknowledge. Not guaranteed if you do the opposite, trying to propagate the Control's changes to the DataSource.
This may go against the internal mechanics used by the Control to notify the changes to its DataSource: a DataGridView notify value changes of its Cells after the Cell edit has completed and validation has been performed.
You could try to call [DataGridView].EndEdit() and Validate(), it doesn't mean that in any circumstance the Control and the DataSource will synchronize when you expect it to happen.
Set the Filter and order the View:
Note that the order is applied to the DefaultView, not the DataTable. The Rows' order in the DataTable remains unchanged.
In your sample code, a filter is set to flag = 1, while you use another name for the Column in row.Cells["flags"].
var dView = (dataGridView2.DataSource as DataTable).DefaultView;
dView.RowFilter = "flag = 1";
dView.Sort = "tw_Name DESC";
When you need to change values in some of the Rows, access the DataTable using the DataGridView.DataSource and cast it to DataTable (or BindingSouce or whatever other source of data you have used).
You can now loop the DataRows and set new values to some Columns base on a condition, as in this case:
var dt = dataGridView2.DataSource as DataTable;
for (int i = 0; i <= dt.Rows.Count - 1; i++) {
var row = dt.Rows[i];
if (row["zazn"] != DBNull.Value && (bool)row["zazn"]) {
row["flag"] = 0;
}
}
You could do the same thing using the DataGridView.Row.DataBoundItem, which is a DataRowView in this case, looping backwards (to only loop the visible Rows):
var dt = dataGridView2.DataSource as DataTable;
//BACKWARDS - also assuming there's a NewRow, so Rows.Count - 2
for (int i = dataGridView2.Rows.Count - 2; i >= 0; i--) {
var row = (dataGridView2.Rows[i].DataBoundItem as DataRowView).Row;
if (row["zazn"] != DBNull.Value && (bool)row["zazn"]) {
row["flag"] = 0;
}
}
If you do the same but with a forward loop:
for (int i = 0; i < dataGridView2.Rows.Count - 1; i++) { ... }
you're in the same situation as before.
I have a Datagridview
1 Drink1 Beef1
2 Drink2 Beef2
3 Drink3 Beef3
But now I want to hide only "Drink3" and the rest stay the same.
I'm only aware of how to hide/remove rows and columns but not sure if it's possible for an individual cell. If it is, what should I apply here? I'm thinking of an datagridview Event but just can't find what it is.
The result should look like this.
1 Drink1 Beef1
2 Drink2 Beef2
3 Beef3
If you want just don't show the value, you can clear it. You now Cell is read-only and you can change the Visible directly.
dataGridView1.Rows[Your Row].Cells[Your Col].Value = null;
If you need cell data you can achieve it from the Data Table.
You can clear the value - but you'll be deleting it from linked data source as well.
Other way to do it would be to set that cell's:
cell.CellStyle.ForeColor = cell.CellStyle.BackColor
cell.CellStyle.SelectionForeColor = cell.CellStyle.SelectionBackColor
Thus making data invisible.
But in this case user can still copy and paste the value, so you'd have to disable copying values from this DataGridView as whole or intercept copy event and if user is copying from "forbidden" cell, just cancel the event.
You can change the cell's style in the backend code, you can change the cell's String value to "".
While you might hide the result as sugested, such as amending your forecolor and back color, I would not recommend it. In some cases (highlited content for instance) it may become visible.
If you don't need to work with the content after you load it into the DataGridView, you can erase the content directly in your data query (SQL, LINQ) or in DataTable.
If you have to work with the content at runtime after you load the DataGridView, than clone source DataTable, hide the content and present that new one. One can figure out more ways to apply this principle.
C#
DataTable dt;
dt = ds.table(0);
for (var ir = 0; ir <= dt.Rows.Count - 1; ir++)
{
DataRow dr = dt.Rows(ir);
if (CStr(dr("MyColumn")) = "Drink3")
{
dr("MyColumn") = " ";
}
}
this.DataGridView1.DataSource = dt;
VB:
Dim dt As DataTable
dt = ds.table(0)
For ir = 0 To dt.Rows.Count - 1
Dim dr As DataRow = dt.Rows(ir)
If CStr(dr("MyColumn")) = "Drink3" Then
dr("MyColumn") = " "
End If
Next
Me.DataGridView1.DataSource = dt
In my web application, I have created
DataTable dt= new DataTable();
dt.Columns.Add("Month");
and made fill the column name "Month" with date as
Month(Column name)
oct-2014
July-2016
Aug-2016
and made fill my dynamic table
Now, i want this dynamic table data to be Reverse order
for eg:
Month(Column name)
Aug-2016
July-2016
oct-2014
like this i need to display dynamic data table is first row is last and last row is first.
Thank you.
Try this.
DataTable reversedDt = dt.Clone();
for (var row = dt.Rows.Count - 1; row >= 0; row--)
reversedDt .ImportRow(dt.Rows[row]);
You can reverse the ordered table.
e.g.
var orderedRows = from row in dt.AsEnumerable().Reverse()
select row;
dataGridView1.DataSource = orderedRows.CopyToDataTable();
Just for anyone's future reference.
I found if you clone the original table then just use a For loop but read from the bottom row up, that is the easiest way.
Also in VB but can easily be converted.
Dim newDataTable = dt.Clone()
For i = 0 To dt.Rows.Count - 1
newDataTable.ImportRow(dt.Rows((dt.Rows.Count - 1) - i))
Next
I'm sending values from one form to another form, then want to display in dgv,
I'm trying this, there is no error during execution, bt it does not show data in dgv..
lineItemsDGV.Rows.Add();
int RowIndex = lineItemsDGV.RowCount - 1;
DataGridViewRow NewRow =lineItemsDGV.Rows[RowIndex];
NewRow.Cells[0].Value = item.Product_id;
NewRow.Cells[1].Value = item.product_name;
NewRow.Cells[2].Value = item.specification;
NewRow.Cells[3].Value = item.unit_price;
NewRow.Cells[4].Value = item.unit_price * 1;
You're close.
What you can do is use the return value of your call to DataGridViewRowCollection.Rows.Add() method, which is the index value of the just added row.
Change your code to this:
int RowIndex = lineItemsDGV.Rows.Add();
DataGridViewRow NewRow = lineItemsDGV.Rows[RowIndex];
NewRow.Cells[0].Value = item.Product_id;
NewRow.Cells[1].Value = item.product_name;
NewRow.Cells[2].Value = item.specification;
NewRow.Cells[3].Value = item.unit_price;
NewRow.Cells[4].Value = item.unit_price * 1;
This is how I would do it:
DataRow rowToAdd= myTable.NewRow();
rowToAdd["ProductId"] = item.Product_id;
rowToAdd["ProductName"] = item.product_name;
rowToAdd["Specification"] = item.specification;
rowToAdd["UnitPrice"] = item.unit_price;
myTable.Add(rowToAdd);
And bind the datatable to the gridview.
I know this thread is old, but I found this page helpful today and this is how I accomplished adding a new row which is different than the previous solutions.
Assumption:
datagridview has columns specified at design time. In my case I had 3 text columns.
The solution is to use the DataGridViewRowCollection.Add functionality and pass a parameter array that contains a list of each column value separated by a comma.
DataGridView1.Rows.Add("Value 1", "Value 2", "Value3")
Using this approach, there's no need to use the BeginEdit, Update or Refesh dgv functions.
I used a CheckedComboBoxEdit control. It is filled by a dataTable. And I checked an item programatically.The following picture shows the output:
It shows that, no items are selected in drop down menu. I did not understand the problem.
Edit: I found the source of the problem. However I do not know, how can I fix this and why it causes the problem.
My code:
rHOP rGetir = new rHOP();
DevExpress.XtraEditors.Repository.RepositoryItemCheckedComboBoxEdit propertiesBaslattigiSurecler = cceBaslattigiSurecler.Properties;
DataTable dt = rGetir.GetirSurecTanim(0, 0);
dt.Columns.Add("Deger", typeof(string));
for (int i = 0; i < dt.Rows.Count; i++)
dt.Rows[i]["Deger"] = dt.Rows[i]["Süreç No"].ToString()
+ "," + dt.Rows[i]["Sürüm"].ToString();
propertiesBaslattigiSurecler.DataSource = dt;
propertiesBaslattigiSurecler.DisplayMember = "Süreç Ad";
propertiesBaslattigiSurecler.ValueMember = "Deger"; // this line causes the problem
cceBaslattigiSurecler.SetEditValue(null);
The dataTable dt has three columns as "Süreç Ad", "Süreç No", "Süreç Ack". Then I added "Deger" column to the dataTable. When I set the ValueMember property to "Deger" column, the problem occurs. When I set the ValueMember property to another column, it works correctly.