WPF Datagrid Get Selected Cell Value - c#

I want to get value for selected cell in datagrid , please anyone tell how to do this. i used SelectedCell changed event , how can i do that?
dataGrid1.CurrentCell

Please refer to the DataGrid Class page on MSDN. From that page:
Selection
By default, the entire row is selected when a user clicks a cell in a DataGrid, and a user can select multiple rows. You can set the SelectionMode property to specify whether a user can select cells, full rows, or both. Set the SelectionUnit property to specify whether multiple rows or cells can be selected, or only single rows or cells.
You can get information about the cells that are selected from the SelectedCells property. You can get information about cells for which selection has changed in the SelectedCellsChangedEventArgs of the SelectedCellsChanged event. Call the SelectAllCells or UnselectAllCells methods to programmatically select or unselect all cells. For more information, see Default Keyboard and Mouse Behavior in the DataGrid Control.
I have added links to the relevant properties for you, but I'm out of time now, so I hope you can follow the links to get your solution.

If you are selecting only one cell then get selected cell content like this
var cellInfo = dataGrid1.SelectedCells[0];
var content = cellInfo.Column.GetCellContent(cellInfo.Item);
Here content will be your selected cells value
And if you are selecting multiple cells then you can do it like this
var cellInfos = dataGrid1.SelectedCells;
var list1 = new List<string>();
foreach (DataGridCellInfo cellInfo in cellInfos)
{
if (cellInfo.IsValid)
{
//GetCellContent returns FrameworkElement
var content= cellInfo.Column.GetCellContent(cellInfo.Item);
//Need to add the extra lines of code below to get desired output
//get the datacontext from FrameworkElement and typecast to DataRowView
var row = (DataRowView)content.DataContext;
//ItemArray returns an object array with single element
object[] obj = row.Row.ItemArray;
//store the obj array in a list or Arraylist for later use
list1.Add(obj[0].ToString());
}
}

When I faced this problem, I approached it like this:
I created a DataRowView, grabbed the column index, and then used that in the row's ItemArray
DataRowView dataRow = (DataRowView)dataGrid1.SelectedItem;
int index = dataGrid1.CurrentCell.Column.DisplayIndex;
string cellValue = dataRow.Row.ItemArray[index].ToString();

I'm extending the solution by Rushi to following (which solved the puzzle for me)
var cellInfo = Grid1.SelectedCells[0];
var content = (cellInfo.Column.GetCellContent(cellInfo.Item) as TextBlock).Text;

If SelectionUnit="Cell" try this:
string cellValue = GetSelectedCellValue();
Where:
public string GetSelectedCellValue()
{
DataGridCellInfo cellInfo = MyDataGrid.SelectedCells[0];
if (cellInfo == null) return null;
DataGridBoundColumn column = cellInfo.Column as DataGridBoundColumn;
if (column == null) return null;
FrameworkElement element = new FrameworkElement() { DataContext = cellInfo.Item };
BindingOperations.SetBinding(element, TagProperty, column.Binding);
return element.Tag.ToString();
}
Seems like it shouldn't be that complicated, I know...
Edit: This doesn't seem to work on DataGridTemplateColumn type columns. You could also try this if your rows are made up of a custom class and you've assigned a sort member path:
public string GetSelectedCellValue()
{
DataGridCellInfo cells = MyDataGrid.SelectedCells[0];
YourRowClass item = cells.Item as YourRowClass;
string columnName = cells.Column.SortMemberPath;
if (item == null || columnName == null) return null;
object result = item.GetType().GetProperty(columnName).GetValue(item, null);
if (result == null) return null;
return result.ToString();
}

//Xaml Code
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=Date, Converter={StaticResource dateconverter}, Mode=OneWay}" Header="Date" Width="100"/>
<DataGridTextColumn Binding="{Binding Path=Prescription}" Header="Prescription" Width="900"/>
</DataGrid.Columns>
//C# Code
DataRowView row = (DataRowView)grid1.SelectedItem;
MessageBox.Show(row["Prescription"].toString() + " " + row["Date"].toString());
As WPF provides binding in DataGrids, this should be rather transparent. However, the following method only works, if you have used SQLDataAdapter and provided a binding path to your DataGridColoumns. For eg. Let's say the above datagrid is named grid1, which has auto generate columns set to false, and is using binding to bind column names to Headers. In this case, we use the 'row' variable of type 'DataRowView' and store the selected row in it. Now, use your Binding Paths, and reference individual columns of the selected row.
Hope this helps! Cheers!
PS: Works if SelectionUnit = 'Row'

Ok after doing reverse engineering and a little pixie dust of reflection, one can do this operation on SelectedCells (at any point) to get all (regardless of selected on one row or many rows) the data from one to many selected cells:
MessageBox.Show(
string.Join(", ", myGrid.SelectedCells
.Select(cl => cl.Item.GetType()
.GetProperty(cl.Column.SortMemberPath)
.GetValue(cl.Item, null)))
);
I tried this on text (string) fields only though a DateTime field should return a value the initiate ToString(). Also note that SortMemberPath is not the same as Header so that should always provide the proper property to reflect off of.
<DataGrid ItemsSource="{Binding MyData}"
AutoGenerateColumns="True"
Name="myGrid"
IsReadOnly="True"
SelectionUnit="Cell"
SelectionMode="Extended">

Worked For me
object item = dgwLoadItems.SelectedItem;
string ID = (dgwLoadItems.SelectedCells[0].Column.GetCellContent(item) as TextBlock).Text;
MessageBox.Show(ID);

These are 2 methods that can be used to take a value from the selected row
/// <summary>
/// Take a value from a the selected row of a DataGrid
/// ATTENTION : The column's index is absolute : if the DataGrid is reorganized by the user,
/// the index must change
/// </summary>
/// <param name="dGrid">The DataGrid where we take the value</param>
/// <param name="columnIndex">The value's line index</param>
/// <returns>The value contained in the selected line or an empty string if nothing is selected</returns>
public static string getDataGridValueAt(DataGrid dGrid, int columnIndex)
{
if (dGrid.SelectedItem == null)
return "";
string str = dGrid.SelectedItem.ToString(); // Take the selected line
str = str.Replace("}", "").Trim().Replace("{", "").Trim(); // Delete useless characters
if (columnIndex < 0 || columnIndex >= str.Split(',').Length) // case where the index can't be used
return "";
str = str.Split(',')[columnIndex].Trim();
str = str.Split('=')[1].Trim();
return str;
}
/// <summary>
/// Take a value from a the selected row of a DataGrid
/// </summary>
/// <param name="dGrid">The DataGrid where we take the value.</param>
/// <param name="columnName">The column's name of the searched value. Be careful, the parameter must be the same as the shown on the dataGrid</param>
/// <returns>The value contained in the selected line or an empty string if nothing is selected or if the column doesn't exist</returns>
public static string getDataGridValueAt(DataGrid dGrid, string columnName)
{
if (dGrid.SelectedItem == null)
return "";
for (int i = 0; i < columnName.Length; i++)
if (columnName.ElementAt(i) == '_')
{
columnName = columnName.Insert(i, "_");
i++;
}
string str = dGrid.SelectedItem.ToString(); // Get the selected Line
str = str.Replace("}", "").Trim().Replace("{", "").Trim(); // Remove useless characters
for (int i = 0; i < str.Split(',').Length; i++)
if (str.Split(',')[i].Trim().Split('=')[0].Trim() == columnName) // Check if the searched column exists in the dataGrid.
return str.Split(',')[i].Trim().Split('=')[1].Trim();
return str;
}

I struggled with this one for a long time! (Using VB.NET) Basically you get the row index and column index of the selected cell, and then use that to access the value.
Private Sub LineListDataGrid_SelectedCellsChanged(sender As Object, e As SelectedCellsChangedEventArgs) Handles LineListDataGrid.SelectedCellsChanged
Dim colInd As Integer = LineListDataGrid.CurrentCell.Column.DisplayIndex
Dim rowInd As Integer = LineListDataGrid.Items.IndexOf(LineListDataGrid.CurrentItem)
Dim item As String
Try
item = LLDB.LineList.Rows(rowInd)(colInd)
Catch
Exit Sub
End Try
End Sub
End Class

you can also use this function.
public static void GetGridSelectedView(out string tuid, ref DataGrid dataGrid,string Column)
{
try
{
// grid selected row values
var item = dataGrid.SelectedItem as DataRowView;
if (null == item) tuid = null;
if (item.DataView.Count > 0)
{
tuid = item.DataView[dataGrid.SelectedIndex][Column].ToString().Trim();
}
else { tuid = null; }
}
catch (Exception exc) { System.Windows.MessageBox.Show(exc.Message); tuid = null; }
}

I was in such situation .. and found This:
int ColumnIndex = DataGrid.CurrentColumn.DisplayIndex;
TextBlock CellContent = DataGrid.SelectedCells[ColumnIndex].Column.GetCellContent(DataGrid.SelectedItem);
And make sure to treat custom columns' templates

I was to dumb to find the Solution...
For me (VB):
Dim string= Datagrid.SelectedCells(0).Item(0).ToString

Mohamed RT had the right idea, and it worked for me. The only thing that seemed to be missing was an explicit cast to TextBlock. By getting the data grid's CurrentColumn.DisplayIndex you are able to define the exact cell that you wish to pull the value of. This also works when the user rearranges the columns. Here is my code:
int columnIndex = yourDataGrid.CurrentColumn.DisplayIndex;
TextBlock targetCell = (TextBlock)yourDataGrid.SelectedCells[columnIndex].Column.GetCellContent(yourDataGrid.SelectedItem);
And to pull out the value of the TextBlock:
MessageBox.Show("Target cell value is: " + targetCell.Text);
Of all the answers I read, this seemed to be the simplest and most robust. Thanks so much Mohamed!

This is my solution to the problem. Only problem left for me with this solution is the posibility of null references.
var Item = ((DataRowView)dataGrid.SelectedCells[0].Item)
.Row
.ItemArray[dataGrid.SelectedCells[0].Column.DisplayIndex];
If you just want a value of a fixed cell in a selected row, you could use this code which is somewhat shorter.
var Item = ((DataRowView)dataGrid.SelectedValue).Row.ItemArray[0];
Don't forget to cast the item into the correct type.

Related

Finding a cell in devexpress datagrid

I'm new to DevExpress GridControl.
I need to find a particular cell in the grid and then do something with it's value.
How do I go about this please?
In the grid's Loaded method, I tried using myGrid.FindRowByValue("ProductType","ABC"), but always gives a negative number.
Thanks.
Here is code you can try
for (int i = 0; i < gridView1.DataRowCount; i++) {
object b = gridView1.GetRowCellValue(i, "FieldName");
if (b != null && b.Equals(<someValue>)){
gridView1.FocusedRowHandle = i;
return;
}
}
you can go to this link for more details.
https://www.devexpress.com/Support/Center/Question/Details/Q132599/get-row-by-cell-value
Unlike XtraGrid, the DXGrid for WPF does not provide the DataRowCount property - that is why we suggested checking the GridControl's ItemsSource. On the other hand, our grid has the VisibleRowCount property, which will be useful in some scenarios.
To accomplish this task, iterate through visible grid rows manually as shown below.
void MoveFocusToLast(GridControl grid, string fieldName, object value) {
for (int i = grid.VisibleRowCount - 1; i >= 0; i--) {
var handle = grid.GetRowHandleByVisibleIndex(i);
var currentValue = grid.GetCellValue(handle, fieldName);
if (currentValue != null && currentValue.Equals(value)) {
grid.View.FocusedRowHandle = handle;
return;
}
}
}
Grid also provides the FindRowByValue method, which allows you to
find a row by a specific cell value. This method returns the handle of
the corresponding row, and you can make that row visible by setting
the FocusedRowHandle property or calling ScrollIntoView. I
have prepared a sample demonstrating this approach.
See Also:
Traversing Rows
Find Row
Get RowHandle from a cell value

Read each cell values in WPF gridview

I have a datagridview in wpf called datagrid1. I need to read value in each cells in datagrid. I know how to do it in windows form
string result = datagrid1.Rows[0].Cells[1].Value.ToString();
How do this in WPF?
There is no easy way to do this in WPF, however this tutorial can be of use to you.
Edit:
First of all I totally agree with the comment Nitin Joshi mentioned above.
Second, According to this answer The WPF datagrid was built to bind to something like a DataTable. The majority of the time, you will modify the DataTable, and the Rows/Columns within the DataTable that is bound to the DataGrid, not the DataGrid it self so you don't need to use something like this datagrid1.Rows[0].Cells[1].Value. But if you still insist on getting the value that way, here is a solution :
Second EDIT:
Since you asked only for a way to read call value, I'll make my answer shorter but also a little more concrete:
GetCellValue method returns a string value representing cell content of a given DataGrid by column/row indices:
I wrote this method assuming column types are either TextBox, TextBlock or ComboBox. Other Types could be handled the same way.
public string GetCellValue(DataGrid datagrid, int row, int column)
{
var cellInfo = new DataGridCellInfo(
datagrid.Items[row], dataGrid.Columns[column]);
DataGridCell cell = null;
var cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
if (cellContent != null)
cell = (DataGridCell)cellContent.Parent;
if (cell == null) return string.Empty;
// if DataGridTextColumn / DataGridComboBoxColumn is used
// or AutoGeneratedColumns is True
if (cell.Content is TextBlock)
return ((TextBlock)cell.Content).Text;
else if (cell.Content is ComboBox)
return ((ComboBox)cell.Content).Text;
// if DataGridTemplateColumn is used
// assuming cells are either TextBox, TextBlock or ComboBox. Other Types could be handled the same way.
else
{
var txtPresenter = FindVisualChild<TextBox>((ContentPresenter)cell.Content);
if (txtPresenter != null) return txtPresenter.Text;
var txbPresenter = FindVisualChild<TextBlock>((ContentPresenter)cell.Content);
if (txbPresenter != null) return txbPresenter.Text;
var cmbPresenter = FindVisualChild<ComboBox>((ContentPresenter)cell.Content);
if (cmbPresenter != null) return cmbPresenter.Text;
}
return string.Empty;
}
public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
Then calling string result = GetCellValue(dataGrid, 2, 1); (e.g. from a Button click event), will return the value of dataGrid[2,1].
*Note:
The SelectionUnit of the DataGrid must be set to Cell.
The DataGridmust fully generated otherwise ItemContainerGenerator returns null.
GetCellValue method works for a few UIElements considered to be more common to be used as DataGridColumn Types.

How to get column name from gridview?

I would like to know how can I get a column name from a gridview? by its number not by name.
like : Name|Age|Birthday: ( so name=0 , age=1 etc...)
thanks.
You can get it like this :
gv.HeaderRow.Cells[i].Text
Or like this :
gv.Rows[0].Cells[i].Text
Rows[0] should be your header row.
//// Header column names
int gridViewCellCount = yourGridView.Rows[0].Cells.Count;
// string array to hold grid view column names.
string[] columnNames = new string[gridViewCellCount];
for (int i = 0; i < gridViewCellCount; i++)
{
columnNames[i] = ((System.Web.UI.WebControls.DataControlFieldCell)(yourGridView.Rows[0].Cells[i])).ContainingField.HeaderText;
}
simply
GridView1.Rows[0].Cells[0].Text;
try this if you want to all the cells value from each of the rows
foreach (GridViewRow r in GridView1.Rows)
{
string s = r.Cells[0].Text;
string y = r.Cells[1].Text;
}
update:
try this
foreach (TableCell Tc in GridView1.HeaderRow.Cells)
{
//if you are not getting value than find childcontrol of TabelCell.
string sssb = Tc.Text;
foreach (Control ctl in Tc.Controls)
{
//Child controls
Label lb = ctl as Label;
string s = lb.Text;
}
}
Revisiting this old question.... it's possible to get the field names of the data bound to a GridView with this kind of code. This makes a dictionary of colnum and field name.
private static IDictionary<int, string> GetGridViewFieldNames(object grid)
{
var names = new Dictionary<int, string>();
var view = grid as GridView;
if (view != null) {
for (var i = 0; i < view.Columns.Count; i++) {
var field = view.Columns[i] as BoundField;
if (field != null) {
names.Add(i, field.DataField);
}
}
}
return names;
}
This is not the answer to the question. It is only the answer if you never change the header text in the gridview. The asker of the question wanted to get the database field name by index.
I've seen a number of "answers" which only provide the text in the selected row of a gridview, or the header text which both do not answer the question that was asked...
You may ask why? If you were going to do audits of updates in a system and wanted to compare old values and new values and only update if they change and want to indicate which field was updated how do you show the database table field name at the index of the loop.
For instance:
Protected Sub gv_RowUpdating(sender As Object, e As System.Web.UI.WebControls.GridViewUpdateEventArgs)
Dim intValCount As Integer = Integer.Parse(e.NewValues.Count)
If intValCount > 0 Then
Dim i As Integer = 0
For i = 0 To intValCount - 1
If Not e.OldValues(i).Equals(e.NewValues(i)) Then
' values have changed, audit the change
Sys.Audits.General(intID, "the_database_table", <the table field by index(i)>, e.OldValues(i).ToString, e.NewValues(i).ToString)
End If
i += 1
Next
End If
End Sub
So the questions is how do you get the database table field name by index via code behind? I too have been searching for this and all the "answers" that I've seen are not the answers I think some of us are really looking for. All the mentioned methods I've seen here are not bullet proof references to a database tables field name.
Its easy: Here i read the gridview header text for each header cell and add them as new columns to a data table.
DataTable dt = new DataTable();
foreach(DataControlFieldHeaderCell column in yourGridview.HeaderRow.Cells)
{
dt.Columns.Add(column.Text.Trim().Replace(" ", ""));
}
//Make sure you do all this after yourGridview.DataBind();
//If you do not want to bind data first simply bind an empty list like so:
/* yourGridview.DataSource = new List<string>();
yourGridview.DataBind(); */

How can i set the value of a datagrid cell using its Column and row index values?

How can i insert a value into a specific datagrid cell by using the cells column and row indexs. I have the Row and Column index saved as ints.
I got the indexs as below. Im basically taking the cell value, the column index and the row index and sending as a serialized XML to java which is sending it back and needs to put it in the same cell.
int column = dataGrid2.CurrentCell.Column.DisplayIndex;
int row = dataGrid2.SelectedIndex;
Thanks,
For a datagrid you access rows through the Items property. The cells are a collection on an item.
dataGrid2.Items[row].Cells[column].Text = "text";
This works as long as the data has been bound to the datagrid during the current page life-cycle. If this is not the case then I believe you are stuck walking the controls.
If you use DataGrid you can try it
DataRowView rowView = (dtGrid.Items[rows] as DataRowView); //Get RowView
rowView.BeginEdit();
rowView[col] = "Change cell here";
rowView.EndEdit();
dtGrid.Items.Refresh(); // Refresh table
To update a WPF DataGridCell programmatically, there could be many ways...
One of the ways is to update value in the bound data item itself. This way the property change notifications will fire for all subscribed visuals including the DataGridCell itself...
Reflection approach
var boundItem = dataGrid2.CurrentCell.Item;
//// If the column is datagrid text or checkbox column
var binding = ((DataGridTextColumn)dataGrid2.CurrentCell.Column).Binding;
var propertyName = binding.Path.Path;
var propInfo = boundItem.GetType().GetProperty(propertyName);
propInfo.SetValue(boundItem, yourValue, new object[] {});
For DataGridComboBoxColumn you would have to extract the SelectedValuePath and use that in place of propertyName.
Otherways include putting cell in edit mode and updating its content value using some behavior in the EditingElementStyle... I find this cumbersome.
Do let me know if you really need that.
I used a variation based upon WPF-it's example to do the whole row and it worked!:
(sender as DataGrid).RowEditEnding -= DataGrid_RowEditEnding;
foreach (var textColumn in dataGrid2.Columns.OfType<DataGridTextColumn>())
{
var binding = textColumn.Binding as Binding;
if (binding != null)
{
var boundItem = dataGrid2.CurrentCell.Item;
var propertyName = binding.Path.Path;
var propInfo = boundItem.GetType().GetProperty(propertyName);
propInfo.SetValue(boundItem, NEWVALUE, new object[] { });
}
}
(sender as DataGrid).RowEditEnding += DataGrid_RowEditEnding;
PS: Be sure that you use value types that are valid for the column (perhaps via a switch statement).
e.g.:
switch on propertyName or propInfo... propInfo.SetValue(boundItem, (type) NEWVALUE, new object[] {});
switch (propertyName)
{
case "ColumnName":
propInfo.SetValue(boundItem, ("ColumnName"'s type) NEWVALUE, new object[] { });
break;
default:
break;
}

How to programmatically set cell value in DataGridView?

I have a DataGridView. Some of the cells receive their data from a serial port: I want to shove the data into the cell, and have it update the underlying bound object.
I'm trying something like this:
SetValueFromSerial (decimal newValue)
{
dataGridView.CurrentCell.Value = newValue;
}
using a string doesn't help:
dataGridView.CurrentCell.Value = newValue.ToString ();
In both cases, I don't see anything in the grid, and the underlying value is unchanged.
I did Google and search here, but I didn't find anything. (I may have missed something, perhaps something obvious, but I'm not utterly lazy.)
If the DataGridView is databound, you shouldn't directly modify the content of the cell. Instead, you should modify the databound object. You can access that object through the DataBoundItem of the DataGridViewRow :
MyObject obj = (MyObject)dataGridView.CurrentRow.DataBoundItem;
obj.MyProperty = newValue;
Note that the bound object should implement INotifyPropertyChanged so that the change is reflected in the DataGridView
dataGridView1[1,1].Value="tes";
If you don't want to modify the databound object from some reason (for example you want to show some view in your grid, but you don't want it as a part of the datasource object), you might want to do this:
1.Add column manually:
DataGridViewColumn c = new DataGridViewColumn();
DataGridViewCell cell = new DataGridViewTextBoxCell();
c.CellTemplate = cell;
c.HeaderText = "added";
c.Name = "added";
c.Visible = true;
dgv.Columns.Insert(0, c);
2.In the DataBindingComplete event do something like this:
foreach (DataGridViewRow row in dgv.Rows)
{if (row.Cells[7].Value.ToString()=="1")
row.Cells[0].Value = "number one"; }
(just a stupid example)
but remember IT HAS to be in the DataBindingComplete, otherwise value will remain blank
I searched for the solution how I can insert a new row and How to set the individual values of the cells inside it like Excel. I solved with following code:
dataGridView1.ReadOnly = false; //Before modifying, it is required.
dataGridView1.Rows.Add(); //Inserting first row if yet there is no row, first row number is '0'
dataGridView1.Rows[0].Cells[0].Value = "Razib, this is 0,0!"; //Setting the leftmost and topmost cell's value (Not the column header row!)
dataGridView1[1, 0].Value = "This is 0,1!"; //Setting the Second cell of the first row!
Note:
Previously I have designed the columns in design mode.
I have set the row header visibility to false from property of the datagridview.
The last line is important to understand:
When yoou directly giving index of datagridview, the first number is cell number, second one is row number! Remember it!
Hope this might help you.
Do you remember to refresh the dataGridView?
datagridview.refresh();
I had the same problem
with sql-dataadapter to update data and so on
the following is working for me fine
mydatgridview.Rows[x].Cells[x].Value="test"
mydatagridview.enabled = false
mydatagridview.enabled = true
I tried a lot of methods, and the only one which worked was UpdateCellValue:
dataGridView.Rows[rowIndex].Cells[columnIndex].Value = "New Value";
dataGridView.UpdateCellValue(columnIndex, rowIndex);
I hope to have helped. =)
Try this way:
dataGridView.CurrentCell.Value = newValue;
dataGridView.EndEdit();
dataGridView.CurrentCell.Value = newValue;
dataGridView.EndEdit();
Need to write two times...
in VB you can use this one
Dim selectedRow As DataRowView
selectedRow = dg.Rows(dg.CurrentCell.RowIndex).DataBoundItem
selectedRow("MyProp") = "myValue"
dg.NotifyCurrentCellDirty(True)
thanks to saeed serpooshan for last row
The following works. I may be mistaken but adding a String value doesn't seem compatible to a DataGridView cell (I hadn't experimented or tried any hacks though).
DataGridViewName.Rows[0].Cells[0].Value = 1;
If the DataGridView has been populated by DataSource = x (i.e. is databound) then you need to change the bound data, not the DataGridView cells themselves.
One way of getting to that data from a known row or column is thus:
(YourRow.DataBoundItem as DataRowView).Row['YourColumn'] = NewValue;
I came across the same problem and solved it as following for VB.NET. It's the .NET Framework so you should be possible to adapt. Wanted to compare my solution and now I see that nobody seems to solve it my way.
Make a field declaration.
Private _currentDataView as DataView
So looping through all the rows and searching for a cell containing a value that I know is next to the cell I want to change works for me.
Public Sub SetCellValue(ByVal value As String)
Dim dataView As DataView = _currentDataView
For i As Integer = 0 To dataView.Count - 1
If dataView(i).Row.Item("projID").ToString.Equals("139") Then
dataView(i).Row.Item("Comment") = value
Exit For ' Exit early to save performance
End If
Next
End Sub
So that you can better understand it.
I know that ColumnName "projID" is 139. I loop until I find it and then I can change the value of "ColumnNameofCell" in my case "Comment". I use this for comments added on runtime.
Just like #Thomas said, the element you want to change must implement INotifyPropertyChanged. But, datasource is also important. It has to be BindingList, which you can create easily from List.
Here is my example - data source is at first DataTable, which I transfer to List and then create BindingList. Then I create BindingSource and use BindingList as DataSource from BindingSource. At last, DataSource from DataGridView uses this BindingSource.
sp_Select_PersonTableAdapter adapter = new sp_Select_PersonTableAdapter();
DataTable tbl = new DataTable();
tbl.Merge(adapter.GetData());
List<Person> list = tbl.AsEnumerable().Select(x => new Person
{
Id = (Int32) (x["Id"]),
Ime = (string) (x["Name"] ?? ""),
Priimek = (string) (x["LastName"] ?? "")
}).ToList();
BindingList<Person> bindingList = new BindingList<Person>(list);
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = bindingList;
dgvPerson.DataSource = bindingSource;
What is also very important: each class's member setter must call OnPropertyChanged(). Without that, it won't work. So, my class looks like this:
public class Person : INotifyPropertyChanged
{
private int _id;
private string _name;
private string _lastName;
public int Id
{
get { return _id; }
set
{
if (value != _id)
{
_id = value;
OnPropertyChanged();
}
}
}
public string Name
{
get { return _name; }
set
{
if (value != _name)
{
_name = value;
OnPropertyChanged();
}
}
}
public string LastName
{
get { return _lastName; }
set
{
if (value != _lastName)
{
_lastName= value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
More on this topic: http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx
private void btn_Addtoreciept_Click(object sender, EventArgs e)
{
serial_number++;
dataGridView_inventory.Rows[serial_number - 1].Cells[0].Value = serial_number;
dataGridView_inventory.Rows[serial_number - 1].Cells[1].Value =comboBox_Reciept_name.Text;
dataGridView_inventory.Rows[serial_number - 1].Cells[2].Value = numericUpDown_recieptprice.Value;
dataGridView_inventory.Rows[serial_number - 1].Cells[3].Value = numericUpDown_Recieptpieces.Value;
dataGridView_inventory.Rows[serial_number - 1].Cells[4].Value = numericUpDown_recieptprice.Value * numericUpDown_Recieptpieces.Value;
numericUpDown_RecieptTotal.Value = serial_number;
}
on first time it goes well but pressing 2nd time it gives me error
"Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index" but when i click on the cell another row appears and then it works for the next row, and carry on ...

Categories

Resources