Focus on a cell of datagrid

Hi

when i  insert a new row in a datagrid  i and i do a new a begin edit on that row  the keypbaord is active and i can modify tha value.
But when  the view is full of rows the beginedit  does not work, so i can't edit progrmmatically the row i ahve inserted.

Someone can heloo me?

Alberto C.



12 Replies

AN Ashok N Syncfusion Team December 26, 2017 11:28 AM UTC

Hi Alberto, 
 
Thanks for contacting Syncfusion support. 
 
We have checked your query and You can edit the GridCell using SfDataGrid.BeginEdit method. Also you can able to scroll the position based on the inserted row position using SfDataGrid.ScrollToRowIndex method. You can get the more details about programmatic scrolling using the below UG link: 
 
 
We have prepared the sample for Edit the particular GridColumn in new inserted record and attached in the below location, please check it. 
 
 
If your requirement was differ from this, please share more details about your requirement, that will be more help us to proceed further. 
 
Regards, 
Ashok 



RS Robert Stevens May 1, 2018 05:24 PM UTC

Hello,

I'm having many issues trying to make the grid function properly for business applications (editing with return key, programmatic editing, etc.).  I care not to delve into all of my issues here but I came across a related issue to this earlier where I can't programmatically focus on any cell that is out of view - that is, I found you basically have to scroll the row into view before you can begin edit?  How can that be the design of the grid?

This has become frustrating for our team as if you look at the documentation for beginEdit() it just says:
The SfDataGrid allows to edit the cell programmatically by calling the SfDataGrid.BeginEdit method. By calling this method, the particular cell enters into edit mode. It edits the data manually or programmatically. To edit a cell programmatically, follow the code example:

this.dataGrid.Loaded += dataGrid_Loaded;
void dataGrid_Loaded(object sender, RoutedEventArgs e)
{
    //Edit the cell at 2nd row,2nd column programmatically
    this.dataGrid.BeginEdit(2, 2);
}

The above works if there is only a couple of rows but as soon as you have more than can fit in the grid, this line of code doesn't work for those rows?  That seems so wrong.

Going further - a solution (workaround) has been provided here in this thread - basically showing you have to scroll first (not in docs) and use a delay (only in sample, not communicated).  I took a look at the provided sample in hopes to find that there were more tricks involved that would fix my other editing and focusing issues...

Here is the proposed solution:
viewModel.OrdersInfo.Add(new OrderInfo() { OrderID = 1234, CustomerID = "1001", EmployeeID = 7654, FirstName = "Michael", LastName = "Irvine", ShipCity = "Boise", ShippingDate = DateTime.Now });
dataGrid.ScrollToRowIndex(dataGrid.View.Records.Count);
await Task.Delay(1000);

dataGrid.BeginEdit(dataGrid.View.Records.Count - 1, 2);


So in addition to the scrolling problem, the official recommendation from Syncfusion here is to have a 1 second delay?  That is, to make the user wait an entire second before the cell is focused?  That's completely unacceptable for my user base who are trying to enter data efficiently.  And from the development side, why aren't we able to just invoke BeginEdit() in any case and have the grid handle it?

Is there any explanation that can be provided for why it is designed this way and any other information that may help me workaround these issues?  I'm finding many scenarios where these magic second delay's are the only way to make it work and that doesn't seem right to me, I don't understand why the documentation doesn't show these requirements for usage.

Thank you,
Robert



JA Jayaraman Ayyanar Syncfusion Team May 2, 2018 07:29 AM UTC

 
Thanks for contacting Syncfusion support. 
 
We have checked your query for the focus on a cell in DataGrid using the BeginEdit. Actually the BeginEdit method will trigger the editing of an element that are only in the view. We have used the virtualization concept in our grid for the performance improvements which will render only the views that are visible in the view and the same elements will be reused upon scrolling. We will not be rendering the views that are not visible on the screen. Hence, it is not possible to begin edit on such element which is not present physically.  However, to edit the values of the elements that are not available in the screen, you can directly edit the values of the underlying collection so that it will reflect in view when those items come to view.  
 
The delay which was given after the ScrollToRowIndex method called is due to the programmatic scrolling will take place asynchronously with an animation. Hence, we need to await till the scrolling is completed and then we can proceed the BeginEdit in the DataGrid which is the actual behaviour of the DataGrid. 
 
Regards, 
Jayaraman. 



RS Robert Stevens May 2, 2018 03:28 PM UTC

Thank you for your reply, unfortunately this isn't helpful - you just confirmed the poor design choice for the grid not to handle the virtualization itself in BeginEdit(), why would BeginEdit() be based on the assumption that the cell is in view when you can only fit a few rows in the grid at a time?  You'd think you could invoke BeginEdit() (per documentation) without the need for the developer to ensure the cell is in view - the grid should bring it into view for you as there is never a case where you would want to BeginEdit() and have absolutely nothing happen (current behavior) - that's a bug in the grid and instead of a workaround provided there should be a bug ticket created.

Additionally - if ScrollToRowIndex is Async and you have to wait for it to finish before focusing - it should be awaitable, not rely on a magic second delay, that's just another workaround.

Lastly - Why is none of this information documented in BeginEdit() API docs and editing on the help site? I'm sure it's for marketing because it would make the controls look hard to use and lower quality.  This has wasted so much of our company time now going into documentation that is simple and reflects a straightforward API, only to find out in the forums there are fundamental design issues that are being hidden from the docs and require poor workarounds.

Design choices aside, the least Syncfusion could do is provide developers the information needed to use their controls right in the docs, not simplify the docs for marketing purposes.  If you want to show simple documentation, you should actually make simple to use controls.

-Syncfusion Customer


RS Robert Stevens May 2, 2018 07:15 PM UTC

Is there anyway to check to see if a cell is in-view?

The delay is a horrible idea - the one second is long enough (very long time for usability) and will work right until it doesn't.  It's literally a matter of row count before that line of code fails and I care not to test how many rows that is.

I prefer to use polling to check for the actual change that is happening in that delay and then you get near-immediate response, and it works all the time.  The only problem is that to do that you have to be able to check for the change, in this case the change is the cell going from out of view, to rendered in the view.  How can I check for this?

Is there a collection in the grid representing the visible rows or anything that would allow me to know if a given row is currently in the view?  This seems absolutely necessary given that the editing/selection methods don't work unless rows are in view.

Example of what I'd like to do at this point:
private async void SetFocusWhenReadyAsync(RowColumnIndex rowColIndex) {
ScrollToRowColumnIndex(rowColIndex.RowIndex, rowColIndex.ColumnIndex);
if (CurrentItem != null) {
// Poll checking the UI for render change
await Task.Run(async () => {
while (!CanFocus(rowColIndex))
await Task.Delay(20);
});
}
BeginEdit(rowColIndex.RowIndex, rowColIndex.ColumnIndex);
}

private Boolean CanFocus(RowColumnIndex rowColIndex) {
var nextItem = DataSource[rowColIndex.RowIndex];
// Pseudo Code
var renderedItem = View.RenderedCollection.Where(p => p.ID == nextItem.ID).FirstOrDefault();
return (renderedItem != null);
}





JA Jayaraman Ayyanar Syncfusion Team May 7, 2018 02:12 AM UTC

 
We have checked your query and the feedback. We agree that our control architecture is designed this way. We consider your feedback and this to be logged as an enhancement in our side in the future. As of now, you can achieve your requirement to check if the cell is in the view by reflecting the line size collection in the VisualContainer and check if that particular line is in the visible region or not. Refer the below code example for the same. 
 
Code logics 
dataGrid.GridLoaded += DataGrid_GridLoaded; 
private void DataGrid_GridLoaded(object sender, GridLoadedEventArgs e) 
        { 
            if (dataGrid != null) 
            { 
                var container = dataGrid.GetType().GetTypeInfo().GetDeclaredProperty("VisualContainer").GetValue(this.dataGrid) as VisualContainer; 
                var visibleRows = container.ScrollRows.GetVisibleLines(); 
                // pass the rowIndex in the below code to check whether row is in the view. 
                var row = visibleRows.FirstOrDefault(x => x.LineIndex == 10); 
 
                if (row != null) 
                { 
                    //row is in view. 
                } 
            } 
        } 
 
We have also prepared a sample to achieve your requirement and you can download the same from the below link. 
 
Regards, 
Jayaraman. 
1


PB Pranay Bajpai June 13, 2018 06:54 PM UTC

Hi,

I am facing a similar issue in my project. I tried to use the above solution but it did not work for me.
I tried the above code in my project to check when I have the row in view but the method GetDeclaredProperty("VisualContainer") always returns null for me.
so your code throws a null exception.

Thanks,
Pranay 



DS Divakar Subramaniam Syncfusion Team June 14, 2018 08:47 AM UTC

Hi Pranay, 
 
We have checked your query. Actually, you can able to get the instance of VisualContainer only after the grid is loaded. If you try to get the VisualContainer before the grid is loaded, then you might get the exception you have experienced. That’s why in our previous update, we have provided the VisualContainer related codes inside the GridLoaded event. So, please ensure that you get the visual container inside the grid loaded event.  
 
If you are using GridLoaded event only and still issue reproducing on your side, then please provide the sample codes you have experienced/used in your application due to which the exception occur which will help us to proceed further. 
 
Regards, 
Divakar. 



PB Pranay Bajpai June 14, 2018 02:51 PM UTC

I have tried to get the VisualContainer in the GridLoaded as well as the  BeginEditWhenReadyAsync method but it comes out to be null in both places.
I am trying to make the BeginEditWhenReadyAsync method to scroll and focus on the desired row.

Sample Code from my project:

using Syncfusion.GridCommon.ScrollAxis;
using Syncfusion.SfDataGrid.XForms;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace CustomDataGrid {
    public class CustomGrid : SfDataGrid {

        private VisualContainer container;

        public CustomGrid() {
            // Subscribe to events
            GridLoaded += OnLoaded;
        }
          
          // Scroll and focus on the row,col
        public async void BeginEditWhenReadyAsync(int RowIndex, int ColumnIndex) {  

            // Slow poll checking the UI for row to appear
            await Task.Run(async () => {
                while (!IsRowInView(RowIndex))
                    await Task.Delay(20);
            });

            BeginEdit(RowIndex, ColumnIndex);

        }

        private bool IsRowInView(int index) {

            var visibleRows = container.ScrollRows.GetVisibleLines();
            if (visibleRows.FirstOrDefault(x => x.LineIndex == index) == null)
                return false;
            return true;
        }

        public void OnLoaded(Object sender, GridLoadedEventArgs e) {
            container = this.GetType().GetTypeInfo().GetDeclaredProperty("VisualContainer").GetValue(this) as VisualContainer;
        }
    }
}




SS Suhasini  Suresh Syncfusion Team June 15, 2018 12:59 PM UTC

Hi Albert, 
 
We checked your query and prepared a sample with SfDataGrid containing the number of rows that fits within the view. And added the new row and edited it programmatically. Editing is done in the newly added row as expected.  
 
Please find the sample in the below link. 
 
Please revert us by modifying the sample attached to reproduce the issue and provide the replication procedure in order to narrow down the issue and provide you with the solution faster. 
 
Regards, 
Suhasini  



PB Pranay Bajpai June 15, 2018 02:53 PM UTC

Suhasini,

Adding a 1 second delay after scrolling and before focusing, as in your sample code has already been ruled out as a potential solution in this thread. Please go through this thread thoroughly before responding again. 

I am trying to implement the solution posted by Jayaraman Ayyanar [Syncfusion] On May 6, 2018 10:12 PM and the container is null for me as I have described earlier. I have modified your solution with my code. Please take a look. 

Thank you,
Pranay Bajpai

Attachment: SfDataGridSample_fe5cc824.zip


SK Shivagurunathan Kamalakannan Syncfusion Team June 19, 2018 04:12 AM UTC

Hi Pranay Bajpai, 
 
We have checked the given sample. The NullRefernce exception in container is reproduced on our side. We had modified the accessed VisualContainer, Since the CustomGrid extends from SfDataGrid. 
 
 
public void OnLoaded(Object sender, GridLoadedEventArgs e)  
{ 
             container = typeof(SfDataGrid).GetTypeInfo().GetDeclaredProperty("VisualContainer").GetValue(this) as VisualContainer; 
 
 } 
 
 
 
Refer the below attached sample link for reference. 
 
Regards, 
Shivagurunathan 


Loader.
Up arrow icon