Read each cell values in WPF gridview - c#

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.

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

How i can get the value of cell in datagrid in wpf?

I have a datagrid, with a number of rows. I want to get the value of cell[0].
In the window form I was using this code:
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
if (dataGridView1.Rows[i].Cells[0].Value == null)
{
//do somthing
}
}
The problem is, I do not know how to get the value of the cell, as this code does not work in WPF.
Like I mentioned in the comments, you need to read more on WPF and bindings that how it works because value which you are trying to get from UI can easily be fetched from underlying data object.
Say you have binded dataGrid to some list ObservableCollection<MyObject> and first column of dataGrid is binded to property Name. You can get value for first cell simply like this:
for (int i = 0; i < dataGridView1.Items.Count; i++)
{
string value = ((MyObject)dataGridView1.Items[0]).Name;
if (String.IsNullOrEmpty(textBlock.Text))
{
// do something.
}
}
That being said, assuming first cell is simple DataGridTextColumn, you can get the value in traditional WinForms way in WPF like this:
for (int i = 0; i < dataGridView1.Items.Count; i++)
{
TextBlock textBlock = dataGridView1.Columns[0]
.GetCellContent(dataGridView1.Items[i]) as TextBlock;
if (textBlock != null)
{
if (String.IsNullOrEmpty(textBlock.Text))
{
// do something.
}
}
}
== is a comparison operator. = is used for assignment:
comboBox3.Text = dataGridView1.Rows[i].Cells[0].Value.ToString();

WPF DataGrid actual ColumnHeaderHeight

When I set a WPF DataGrid's ColumnHeaderHeight to Auto (double.NaN), how do I get the actual rendered height of the column header?
I cannot seem to find the property in the DataGrid class.
You could get hold of it by searching through the visual tree for the DataGridColumnHeadersPresenter and reading its ActualHeight property.
var headersPresenter = FindVisualChild<DataGridColumnHeadersPresenter>(dataGrid);
double actualHeight = headersPresenter.ActualHeight;
Here's the FindVisualChild method. It could be implemented as an extension method as well.
public static T FindVisualChild<T>(DependencyObject current) where T : DependencyObject
{
if (current == null) return null;
int childrenCount = VisualTreeHelper.GetChildrenCount(current);
for (int i = 0; i < childrenCount ; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(current, i);
if (child is T) return (T)child;
T result = FindVisualChild<T>(child);
if (result != null) return result;
}
return null;
}
When I remember correctly, the property is an attached property - meaning the real value should be found on a DataGridColumn.
There is a separate class for the DataGridColumnHeader with the same name - see: http://msdn.microsoft.com/de-de/library/system.windows.controls.primitives.datagridcolumnheader(v=vs.110).aspx
This class can probably be gained through a single DataGridColumns "Header" property.
See: http://msdn.microsoft.com/en-us/library/system.windows.controls.datagridcolumn.header(v=vs.110).aspx
So I would grab the first column of the grid, convert it's Header property to DataGridColumnHeaderand read its actualheight attribute.
Please make sure to guard for the case that the Header attribute or ActualHeight is null - this can happen when the grid is build / refreshing or closing. I dimly remeber that there should be an event which is fired when the grid is rendered completely.

Adding a row to a datagrid and retrieving new values from each cell

I need to get each value of each cell in a row. First when I add the data to the new row. The data goes away after hitting enter - however it is in my ObservableCollection.
I have an ObservableCollection<object> which I set up so that I can re-use the Datagrid. For instance I have an ObservableCollection<object> which holds multiple CommissionOperator (db/linq object) objects in it. After I insert the new data into the grid, I get ,lets say, 10 CommissionOperator objects in my ObservableCollection and one object object in my ObservableCollection.
Now, I am trying to figure out how to get the value from the Datagrid. So I did some research and came up with this (from a question I cant find at the moment to link):
//in a class that inherits from DataGrid
public Microsoft.Windows.Controls.DataGridCell GetCell( int column )
{
Microsoft.Windows.Controls.DataGridRow rowContainer = GetRow(this.SelectedIndex);
if (rowContainer != null)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>( rowContainer );
// Try to get the cell but it may possibly be virtualized.
Microsoft.Windows.Controls.DataGridCell cell = (Microsoft.Windows.Controls.DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex( column );
if (cell == null)
{
// Now try to bring into view and retreive the cell.
this.ScrollIntoView( rowContainer, this.Columns[column] );
cell = (Microsoft.Windows.Controls.DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex( column );
}
return cell;
}
return null;
}
public Microsoft.Windows.Controls.DataGridRow GetRow( int _currentRowIndex )
{
Microsoft.Windows.Controls.DataGridRow row = (Microsoft.Windows.Controls.DataGridRow)this.ItemContainerGenerator.ContainerFromIndex( _currentRowIndex );
if (row == null)
{
// May be virtualized, bring into view and try again.
this.UpdateLayout();
this.ScrollIntoView( this.Items[_currentRowIndex] );
row = (Microsoft.Windows.Controls.DataGridRow)this.ItemContainerGenerator.ContainerFromIndex( _currentRowIndex );
}
return row;
}
public static T GetVisualChild<T>( Visual parent ) where T : Visual
{
T child = default( T );
int numVisuals = VisualTreeHelper.GetChildrenCount( parent );
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild( parent, i );
child = v as T;
if (child == null)
{
child = GetVisualChild<T>( v );
}
if (child != null)
{
break;
}
}
return child;
}
So I end up doing something like this:
((TextBox) (RGVDataSelector.GetCell(1).Content)).Text
Now I get an error saying that I cannot cast TextBlock into a TexBox and the TextBlock.Text is empty...
Im just trying to figure out how to get the data from the DataGrid when I enter data into a new row...
Here is how my ObservableCollection looks after adding the new row:
Here is how the DataGrid is during adding (just as a reference)
Here is the DataGrid after insert
Which I figure if I can just get the data from out of the cell that I can rebind the DataGrid or update the bindings or something to get it to show the right data.
Could this be happening because the data is disappearing from my DataGrid that I cannot actually get the data from that cell?

WPF Datagrid Get Selected Cell Value

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.

Categories

Resources