We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

Iterate through DataGridRow

I have the following code for DataGrid in WPF. Now I want to do the same with in Xamarin.Forms with the SFDataGrid. How can I do that?
Here is the code I use in WPF:

//get highest or lowest value for each column
public static List<int[]> GetColumnValue(DataGrid dg, string sproc, bool getMax)
{
    try
    {
//no dg.Items in Xamarin.Forms
        if (null == dg.Items) return null;
       
        List<int[]> list = new List<int[]>();
        string[] columns = dg.Columns.Where<DataGridColumn>(s => !IsSkipColumn(s.Header.ToString())).Select<DataGridColumn, string>(s => s.Header.ToString()).ToArray<string>();
        int col = -1;

        for (int i = 0; i < columns.Length; i++)
        {
            //create int[] for column and cell position, set default value for val
            int[] arr = new int[2];
            decimal val = (getMax) ? 0 : 99999999999;
            Dictionary<int[], decimal> values = new Dictionary<int[], decimal>();                   

            //no DataRowView in Xamarin.Forms
            foreach (DataRowView rv in dg.Items)
            {
//Xamarin.Forms: dg.ItemContainerGenerator ???
                DataGridRow dgrow = (DataGridRow)dg.ItemContainerGenerator.ContainerFromItem(rv);

                if (null != dgrow)
                {
                    col = -1;
                    int row = dg.ItemContainerGenerator.IndexFromContainer(dgrow);
                    if (SkipRow(skipRows, row)) continue;

                    //itereate through each column
                    foreach (DataGridColumn column in dg.Columns)
                    {
                        col++;
                        //if column matches columns item
                        if (column.Header.ToString() == columns[i])
                        {
                            if (column.GetCellContent(dgrow) is TextBlock)
                            {
                                TextBlock cellContent = column.GetCellContent(dgrow) as TextBlock;
                                string text = cellContent.Text.Replace(".", "").Replace("€", "").Replace("%", "").Replace(" ", "");
                                       
                                        //check if text is a decimal value
                                        if (Helper.IstDecimal(text))
                                        {
                                            if (getMax && val < Convert.ToDecimal(text))
                                            {
                                                val = Convert.ToDecimal(text);
                                                arr[0] = dg.ItemContainerGenerator.IndexFromContainer(dgrow);
                                                arr[1] = col;
                                            }

                                            if (!getMax && val > Convert.ToDecimal(text))
                                            {
                                                val = Convert.ToDecimal(text);
                                                arr[0] = dg.ItemContainerGenerator.IndexFromContainer(dgrow);
                                                arr[1] = col;
                                            }

                                            values.Add(new int[] { dg.ItemContainerGenerator.IndexFromContainer(dgrow), col }, Convert.ToDecimal(text));
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }

                    CheckSameValues(values, list, val);

                   // list.Add(arr);
                }

                return list;
}.....

Thanks for any help.

13 Replies

DS Divakar Subramaniam Syncfusion Team October 5, 2016 10:33 AM UTC

Hi Thomas, 
 
 
Thanks for contacting Syncfusion Support. 
 
 
We have checked your query. If your need is to get the data rows, then it is possible to access the data row using SfDataGrid.GetRowGenerator() method as in below code snippet. 
 
//Get DataRow 
var row = dataGrid.GetRowGenerator().Items; 
  
 
Also, you can able to get the row index of the data row as follows. 
 
//Get the index of particular DataRow 
var row = dataGrid.GetRowGenerator().Items.IndexOf(item); // where item is a DataRow 
 
 
If you need to get the row data of the rows, then it is possible to get the data using SfDataGrid.Views.Records as in below code snippet. 
 
foreach(var item in dataGrid.View.Records) 
{ 
    //Get the row data of the rows 
    var rowData = item.Data; 
} 
 
 
We have prepared the sample based on your query and you can download the same from the below link. 
 
 
 
 
 
Regards, 
Divakar. 



TG Thomas Gruener October 5, 2016 01:45 PM UTC

OK, now I have the DataRow, but how I get the cell content for each column of that row?

foreach(GridTextColumn gc in dg.Columns)   or    foreach(GridTextColumn gc in DataRow.Columns)   ??????
{
          cell = ????
          text = cell.value ???  or something like that
}

Thanks


DS Divakar Subramaniam Syncfusion Team October 6, 2016 04:38 AM UTC

Hi Thomas, 
 
 
In SfDataGrid, it is possible to get the cell content for each column using SfDataGrid.GetCellValue(RowData,ColumnName) method. Please refer the below code snippet to know how to get the cell content for each column. 
 
 
foreach (var item in dataGrid.View.Records) 
{ 
    //Get the row data of the rows 
    var rowData = item.Data; 
 
    foreach (var column in dataGrid.Columns) 
    { 
        //Get the cell value for each column 
        var cellValue = dataGrid.GetCellValue(rowData, column.MappingName); 
    } 
} 
 
 
Also, we have prepared the sample based on your query and you can download the same from the below link. 
 
 
 
 
Regards, 
Divakar. 
 



TG Thomas Gruener October 6, 2016 08:31 AM UTC

Thanks, for all your help so far.
Now I only need to know, how I can apply some values to the cell, like Background color.

foreach (var column in dataGrid.Column)
{
      var cellValue = dataGrid.GetCellValue(rowData, column.MappingName);
     
     if(cellValue == "Val")
     {
            //need something like this:
           dg.Cell.Backgroundcolor = Colors.Red;
      }
}

Thanks


DS Divakar Subramaniam Syncfusion Team October 7, 2016 07:07 AM UTC

Hi Thomas, 
 
 
In SfDataGrid, you can able to apply styles like background color, foreground color for the particular column using GridColumn.CellStyle property. Please refer the below code snippet to know how to apply styles for the particular column. 
 
Style style = new Style(typeof(GridCell)); 
style.Setters.Add(new Setter() { Property = GridCell.BackgroundColorProperty, Value = Color.Blue}); 
 
foreach (var column in sfGrid.Columns) 
{ 
    if (column.MappingName == "CustomerID") 
        column.CellStyle = style; 
} 
 
 
Also, you can able to apply styles for the particular cell in the column based on the cell content using Converter. Please refer the below KB link to know how to apply styles for the particular cell in a column based on the cell content. 
 
 
 
However, we have prepared a sample by applied styles for particular cell and you can download the same from the below link. 
 
 
 
 
Regards, 
Divakar. 



TG Thomas Gruener October 7, 2016 07:26 AM UTC

Thank you for your help, but that was not exactly what I needed, since I had already read this article. But I need to be able to apply a style to an induvidual cell and not to each cell in that column. See Sample:

foreach(var column gc in dataGrid.Columns)
{
           var cellvalue = dataGrid.GetCellValue(record.Data, column.MappingName);
           if(cellvalue == "test")
           {
                 foreach(GridCell gc in column.Cells)  ???   something like that
                 {
                       cell = ????
                       gc .Style = new Style(GridCell,BackgroundColor, "Red");  ????   something like that
                  }
            }
}

This way I can give each induvidual cell a style and not the whole column. I need this since we have multiple values that should be highlighted in deifferent colors, dependent on their values.

Thanks


DS Divakar Subramaniam Syncfusion Team October 7, 2016 09:18 AM UTC

Hi Thomas, 
 
 
In SfDataGrid, it is not possible to iterate each cell in the column since SfDataGrid is implemented virtualization concept. So, it is not possible to get the cell value as you mentioned in your code. However, you can able to set a style for the particular cell using GridColumn.CellStyle property and Converter as we said in our previous update. In the Converter, you can able to get the value of each cell in the column which you have bound to the converter. Please refer the below code snippet to know how to apply the style to the particular cell using Converter. 
 
 
//Main Page 
Style style = new Style(typeof(GridCell)); 
style.Setters.Add(new Setter() { Property = GridCell.BackgroundColorProperty, Value = new Binding() { Path = "OrderID", Converter = new Converter() } }); 
 
foreach (var column in sfGrid.Columns) 
{ 
    if (column.MappingName == "OrderID") 
        column.CellStyle = style; 
} 
 
//Converter class 
public class Converter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
        var data = (int)value; 
        if (data == 10004) 
            return Color.Blue; // You can achieve your requirement here.(applying styles for particular cell based on the cell value) 
        return Color.Default; 
    } 
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
        return null; 
    } 
} 
 
 
In the converter, you will get the values of the property you bound. In the above code, we have bound “OrderID” property. So, you can get each value of the “OrderID” column. Hence, you can apply a style to any cell based on the cell value as above. We have applied background color for the cell having the value as 10004 in the above code. You can modify the code based on your requirement and can apply different styles to the particular cell. 
 
We have explained the same in the sample which we provided in the previous update also. 
 
 
 
Regards, 
Divakar. 



TG Thomas Gruener October 11, 2016 02:26 PM UTC

Hi,
this won't work for me, because I need to highlight all the lowest and all the highest values of a column.
I created some work around which should normally work, but for some reason it doesn't apply the styles.
Please check the files in the Attachment. Just copy paste them into the PCL part of the Project to test them.
The code iterates through all items and columns, and keeps the row and item number stored in an Array.
Than it makes a second iteration through it to set the Styles.

Please let me know if you can find the Problem why this doesn't work as it should????

Attachment: ConverterDemo_fb4f1870.zip


DS Divakar Subramaniam Syncfusion Team October 12, 2016 06:38 AM UTC

Hi Thomas, 
 
 
We have checked your sample. In the sample, you have set the style for the cells in SfDataGrid.GridLoaded event. Before this event triggered, SfDataGrid will be initialized. That’s why the converter in your sample is not worked. However, you can overcome this problem by applying the styles in SfDataGrid.GridViewCreated event as in below code snippet. 
 
sfGrid.GridViewCreated += SfGrid_GridViewCreated; 
 
private void SfGrid_GridViewCreated(object sender, GridViewCreatedEventArgs e) 
{ 
    SfDataGrid dg = (SfDataGrid)sender; 
    //get the max items and min items from Grid for each column 
    List<int[]> maxList = GetColumnValue(dg, true); 
    List<int[]> lowList = GetColumnValue(dg, false); 
 
    //highlight the cells 
    HighLightCells(dg, lowList, true); 
    HighLightCells(dg, maxList, false); 
} 
 
 
We have modified your sample by resolved your problem and you can download the same from the below link. 
 
 
 
 
Regards, 
Divakar. 



TG Thomas Gruener October 12, 2016 08:41 AM UTC

Thank you for your help. Well now it works, but the Style is always applied to the complete column, but I only want to change the style of the induviual cell.
Exactly like it is demonstrated here: https://www.syncfusion.com/kb/3176/how-to-improve-performance-when-using-formatting-and-styling-for-the-cells-based-on-data
In this sample you can see that the style is applied to each induvidual cell, and not to the whole column.
Is something possible with SFDatagrid iOS?

or maybe something like this:

Style style = new Style(typeof(GridCell));
if(isMin)
{
    style.Setters.Add(new Setter() { Property = GridCell.BackgroundColorProperty, Value = new Binding() { Path = column.MappingName, Converter = new Converters.GridHighlightRedConverter() } });
}
else
{
    style.Setters.Add(new Setter() { Property = GridCell.BackgroundColorProperty, Value = new Binding() { Path = column.MappingName, Converter = new Converters.GridHighlightGreenConverter() } });
}

//this doesn't work, I get Null for GridCellRendererBase
GridCellRendererCollection grc = dg.CellRenderers;
foreach(GridCellRendererBase gr in grc)
{
    if(gr.CurrentCellIndex.RowIndex == intArr[0] && gr.CurrentCellIndex.ColumnIndex == intArr[1])
    {
        gr.CurrentCellElement.Style = style;
    }
}



Or is it possible to create a StyleSelector like it is demonstrated here, because I still could make a workaround to get the min and max value.
I tried but I can not find the Namespace for the StyleSelector wtih (SFDataGrid iOS).
public class CustomCellStyleSelector : StyleSelector
{
    public override Style SelectStyle(object item, System.Windows.DependencyObject container)
    {
            var gridCell = container as GridCell;
            var mappingName = gridCell.ColumnBase.GridColumn.MappingName;            
            var record = gridCell.DataContext;
            var cellValue = record.GetType().GetProperty(mappingName).GetValue(record);

            if (mappingName.Equals("OrderID"))
            {
                if (Convert.ToInt16(cellValue) <= 1005)
                    return App.Current.Resources["cellStyle1"] as Style;
                else
                    return App.Current.Resources["cellStyle2"] as Style;
            }
            return base.SelectStyle(item, container);
    }
}


Thanks for all your help so far, I really appreciate it.



DS Divakar Subramaniam Syncfusion Team October 13, 2016 11:04 AM UTC

Hi Thomas, 
 
 
If you need to achieve conditional formatting in Xamarin.iOS, then it is not possible to achieve using Style and StyleSelector since these classes are not available in Xamarin.iOS. However, you can set the text color based on the cell value in Xamarin.iOS by deriving a custom cell. In the LayoutSubviews() override of the custom cell, you can achieve your requirement as in below code snippet. 
 
 
public override void LayoutSubviews () 
{ 
    label.Frame =new CGRect(35,0,this.Frame.Width,this.Frame.Height) ;             
    label.Text =DataColumn.FormattedCellvalue; 
     
    if (label.Text == "Red") 
        label.TextColor = UIColor.Red; 
    else if (label.Text == "Green") 
        label.TextColor = UIColor.Green; 
    else if (label.Text == "Yellow") 
        label.TextColor = UIColor.Yellow; 
    else if (label.Text == "Orange") 
        label.TextColor = UIColor.Orange; 
    else 
        label.TextColor = UIColor.White;     
 
    base.LayoutSubviews (); 
} 
  
 
We have prepared a sample based on your query and you can download the same from the below link. 
 
 
 
 
Regards, 
Divakar. 



ER Ernest March 15, 2018 03:43 PM UTC

Accept


SK Suriya Kalidoss Syncfusion Team March 16, 2018 06:24 AM UTC

Hi Vincet, 
 
We are glad that your issue has been resolved. Please let us know if your require any further assistance.  
 
Regards, 
Suriya 


Loader.
Live Chat Icon For mobile
Up arrow icon