This is a migrated thread and some comments may be shown as answers.

Scrolling via tab on editable grid

9 Answers 137 Views
GridView
This is a migrated thread and some comments may be shown as answers.
christina noel
Top achievements
Rank 1
christina noel asked on 14 Dec 2011, 06:22 PM
Hello,

I am constructing something that we call a "fully editable grid". The basic idea behind this grid is that the user can do data entry into the grid as seamlessly as possible. The general workflow is that, once we have loaded in our ItemsSource, we use BeginInsert() to give the user a new row to start typing in. We trap the RowLoaded event to automatically put the first editable column of the inserted row in edit mode.  The user can then type in and tab through the columns to the end.

We have both cell and row validation. We then trap the RowEditEnd event (which only fires after everything has validated) to do a BeginInsert() to give them another new row.

This is working extremely well except for one major problem: When the grid is wide enough that it needs to scroll, I can't get it to scroll back to the first column when inserting the new row. My code is currently putting the right cell in edit mode, but calling ScrollintoView isn't doing anything, and ScrollintoViewAsync is coming back into the "failed" callback. I've got both column and row virtualization turned off, and I'm kind of at my wits end on this one.

Here's some code snippets, so maybe you can figure out where my bad setting is, or what else I need to do to make this work.
<telerik:RadGridView x:Name="grdFiles"  SelectionMode="Extended" telerik:StyleManager.Theme="{StaticResource MPTheme}" ItemsSource="{Binding JournalItemView}"
          AutoGenerateColumns="false"  Grid.Row="1" CanUserFreezeColumns="false" RowHeight="20" CanUserReorderColumns="False" RowIndicatorVisibility="Visible"
                  CanUserResizeColumns="True" CanUserSortColumns="True" CanUserDeleteRows="{Binding CanEdit}" CanUserInsertRows="{Binding CanEdit}" ShowGroupPanel="False" IsFilteringAllowed="False"
                  ShowColumnFooters="True" RowEditEnded="grdFiles_RowEditEnded" AddingNewDataItem="grdFiles_AddingNewDataItem" RowLoaded="grdFiles_RowLoaded" ValidatesOnDataErrors="InEditMode"
                  RowValidating="grdFiles_RowValidating" ScrollMode="RealTime" EnableColumnVirtualization="false" EnableRowVirtualization="False" Height="470" CurrentCellChanged="grdFiles_CurrentCellChanged"
                  IsReadOnly="{Binding CanEdit, Converter={StaticResource NotConverter}}"  ElementExporting="grdFiles_ElementExporting" Deleted="grdFiles_Deleted"
                  ColumnWidthChanged="grdFiles_ColumnWidthChanged" FrozenColumnCount="1" ActionOnLostFocus="None" SelectionUnit="FullRow" CanUserSelect="False" IsSynchronizedWithCurrentItem="False" >
     <telerik:RadGridView.Columns>
         <telerik:GridViewSelectColumn UniqueName="SelectColumn" />
          ---6 editable grid columns---
     </telerik:RadGridView.Columns>
 </telerik:RadGridView>
private void ViewModel_Populated(object sender, EventArgs e)
 {
     grdFiles.BeginInsert();
 }
 
private void grdFiles_AddingNewDataItem(object sender, GridViewAddingNewEventArgs e)
 {
     e.NewObject = ViewModel.NewObject();
 }
 
 private void grdFiles_RowLoaded(object sender, RowLoadedEventArgs e)
 {
     if (e.Row is GridViewRow)
     {
         if (e.Row.IsCurrent)
         {
              grdFiles.CurrentColumn = grdFiles.Columns[1];
             (e.Row as GridViewRow).BeginEdit();
             grdFiles.ScrollIntoView(e.Row.Item, grdFiles.Columns[1]);   //Doesn't work
         }
     }
 }
 
 private void grdFiles_RowEditEnded(object sender, Telerik.Windows.Controls.GridViewRowEditEndedEventArgs e)
 {
     int rowIdx = grdFiles.Items.Cast<ValidatingJournalItem>().ToList().IndexOf(e.Row.Item as ValidatingJournalItem);
     if (e.EditAction != GridViewEditAction.Cancel)
     {
             if (rowIdx + 1 == grdFiles.Items.Count && BaseViewModel.HasItemChanged(e.NewData, e.OldValues))
             {
                 grdFiles.BeginInsert();  //Start new row if data was entered
             }
             else if (rowIdx + 1 == grdFiles.Items.Count)
             {
                 grdFiles.CurrentColumn = grdFiles.Columns[1];  //Go back to first column if nothing was changed
                 grdFiles.ScrollIntoView(e.Row.Item, grdFiles.Columns[1]);   //doesn't work.
             }
        
     }
 }

Any help you can give me will be appreciated!

--Christina

9 Answers, 1 is accepted

Sort by
0
Ivan Ivanov
Telerik team
answered on 19 Dec 2011, 05:39 PM
Hi Christina Noel,

Would you please share with us why you have turned off the virtualization? Such a decision will surely lead to performance problems. As for the scrolling problem, I would advise you to use ScrollIntoViewAsync with enabled virtualization. For more extensive info you may refer to this article.

Kind regards,
Ivan Ivanov
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
christina noel
Top achievements
Rank 1
answered on 19 Dec 2011, 08:11 PM
Thanks for the reply.

I don't know if it's important, but I forgot to mention I'm also handling the CurrentCellChanged event in order to automatically put a clicked cell into editmode (instead of having to click twice). This is also what is putting the correct cell into edit mode when changing rows via tab. (Please note that I've changed my grid name from grdFiles to grdJournals. It's the same grid as I listed below).

private void grdJournals_CurrentCellChanged(object sender, GridViewCurrentCellChangedEventArgs e)
        {
            if(!grdJournals.Items.IsEditingItem && !grdJournals.Items.IsAddingNew && e.NewCell != null && e.NewCell.ParentRow is GridViewRow)
            {
                e.NewCell.IsInEditMode = true;
                e.Handled = true;
             }
        }

I turned off column virtualization because when it's on tabbing doesn't work properly. The grid will only tab through editable columns that are visible instead of scrolling to the right as you tab. I don't care whether row virtualization is on or not for the most part. We've got our grid height set for showing 20 rows and aren't expecting normal use to go above 10, so the performance for many rows was not an issue.

I turned on row and column virtualization and used the following code:
grdJournals.ScrollIntoViewAsync(e.Row.Item, grdJournals.Columns[1],
                a =>
                {
                    SetTestText("scroll succeeded");
                    grdJournals.CurrentColumn = grdJournals.Columns[1];
                    (e.Row as GridViewRow).BeginEdit();
                },
                () =>
                {
                    SetTestText("scroll failed");
                    grdJournals.CurrentColumn = grdJournals.Columns[1];
                    (e.Row as GridViewRow).BeginEdit();
                });

(with the begin edit lines left off of the version in roweditended).

When I manually scroll to the right, click in the last cell and hit tab:
1) If it's not the last row, the last cell in the row loses edit, but remains current.
2) If it is the last row, the code hits "scroll failed" in roweditended and then calls currentcellchanged with e.NewCell=null. When I scroll back to the left, it looks like the first cell in the last row is current, but it is not in edit mode.
3) If it's the last row and I'm inserting a new row, it inserts a new row, then hits "scroll failed" in rowloaded and behaves similarly to (2).

With the exact same code, but with column virtualization off:
1) If it's not the last row, something (I'm guessing the built in lost focus code) calls currentcellchanged with e.NewCell equal to the first editable cell on the next row.
2) if it is the last row, the code hits "scroll failed" in roweditended, and then calls currentcellchanged with e.NewCell equal to the first editable cell on the last row.
3) If it's the last row and I'm inserting a new row, the code hits "scroll failed" in rowloaded and behaves similarly to (2).

I need the behavior listed in this second group, except that I also need the scrolling to work!

--Christina


0
Ivan Ivanov
Telerik team
answered on 22 Dec 2011, 04:46 PM
Hello,

I presume that your custom logic interferes with RadGridView's default keyboard navigation. By design, when the Tab key is pressed RadGridViewCommands.MoveNext is invoked. Apparently, when the last cell of a row is edited, the "next cell" is the first from the next row. However, you can override this default behavior by using the custom KeyboardCommandProvider mechanism. Here is an article that will help you to implement it in your scenario.

Kind regards,
Ivan Ivanov
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
christina noel
Top achievements
Rank 1
answered on 22 Dec 2011, 08:53 PM
What follows is an exhaustive analysis of the tabbing behavior of the RadGridView. I commented out all my code that is inserting rows; adjusting the current item, column, or cell; or adjusting editmode. I think this puts me back at the default tabbing behavior. I also turned on the RowIndicator column to see if that would give me more info.

I then ran a simple experiment, starting with a blank grid (Please note that when I say "first cell" in the following description, it's actually the second cell, since the first column is a clientselectcolumn). I also assume that when a cell has an extra border, then it's the current cell. My theme is set to Office Blue, if that makes a difference. I've highlighted in bold things that I consider to be incorrect behavior.

With column virtualization on:
  • Press Insert (inserts a new row, First cell enters edit mode, Row Indicator briefly shows ">", then Edit).
  • Press Tab (Next cell enters edit mode).
  • Press Tab -- next column is offscreen (Cell exits edit mode, stays current, Row Indicator shows blank).
  • Continuing to Press Tab does nothing, so scrolled all the way to right.
  • Click in last cell (makes it current).
  • Click in last cell again (Cell enters edit mode, Row Indicator shows Edit).
  • Press Tab (Cell exits edit mode, stays current, Row Indicator shows blank).
  • Press Insert (inserts a new row, new row shows the symbol ">", current cell doesn't change)
  • Click in last cell of first row (Cell enters edit mode, Row indicator shows Edit for first row, > for new row)
  • Press Tab (Cell exits edit mode, stays current, Row Indicator shows blank for first row, > for new row)

I restarted with a new blank grid, with column virtualization off:

  • Press Insert (inserts a new row, First cell enters edit mode, Row Indicator briefly shows ">", then Edit).
  • Press Tab (Next cell enters edit mode).
  • Press Tab when next column is offscreen (Grid scrolls to right, next cell enters edit mode).
  • Tab to last cell (Grid continues to scroll, last cell in edit mode).
  • Press Tab (Cell exits edit mode, stays current, Row Indicator shows blank).
  • Press Insert (inserts a new row, new row shows ">", current cell doesn't change)
  • Click in last cell of first row (Cell enters edit mode, Row indicator shows Edit for first row, > for new row)
  • Press Tab (Cell exits edit mode, first cell on new row is current, Row Indicator shows blank for first row, > for new row, no scroll)

As you can see, column virtualization is still not respecting column tabbing for columns that are off-screen.

I then switched "IsSynchronizedWithCurrentItem" to true and reran the tests.
With column virtualization on:

  • Press Insert (inserts a new row, First cell enters edit mode, Row Indicator briefly shows ">", then Edit, Row is Selected).
  • Press Tab (Next cell enters edit mode).
  • Press Tab when next column is offscreen (Grid scrolls to right, next cell enters edit mode).
  • Tab to last cell (Grid continues to scroll, last cell in edit mode).
  • Press Tab (Cell exits edit mode, stays current, Row Indicator shows blank, Row is still Selected).
  • Press Insert (nothing happens)
  • Click outside of Grid, Press Insert (Inserts a new row, New row shows ">", New row is selected, current cell doesn't change)
  • Click in last cell of first row (Cell enters edit mode, Row indicator shows Edit for first row, > for new row, new row is selected)
  • Press Tab (Cell exits edit mode, stays current, Row Indicator shows blank for first row, > for new row, new row is selected)

With column virtualization off:

  • Press Insert (inserts a new row, First cell enters edit mode, Row Indicator briefly shows ">", then Edit, Row is Selected).
  • Press Tab (Next cell enters edit mode).
  • Press Tab when next column is offscreen (Grid scrolls to right, next cell enters edit mode).
  • Tab to last cell (Grid continues to scroll, last cell in edit mode).
  • Press Tab (Cell exits edit mode, stays current, Row Indicator shows blank, Row is still Selected).
  • Press Insert (Inserts a new row, New row shows ">", New row is selected, current cell doesn't change, First row is unselected)
  • Click in last cell of first row (Cell enters edit mode, Row indicator shows Edit for first row, > for new row, new row is selected)
  • Press Tab (Cell exits edit mode, First cell of new row is current, Row indicator show blank for first row, > for new row, new row is selected, no scroll)

Aside from the fact that I don't want the row to be selected just because you happen to be editting it (Selection has no use except for deleting rows in my current implementation), Column virtualization behaves better for this -- except for the fact that it seems to ignore "Insert" while focus is in a cell. There seems to be no difference for column virtualization off.

I then went back and tried each of the following statements in RowEditEnded (in separate cases), to see if I could get scrolling to work in any of the above cases.

  1. grdJournals.ScrollIntoView(grdJournals.Items[0],grdJournals.Columns[1]);
  2. grdJournals.ScrollIntoView(grdJournals.Items[0],grdJournals.Columns["Date"]);
  3. grdJournals.ScrollIntoViewAsync(grdJournals.Items[0],grdJournals.Columns[1], a=>{SetTestText("scrolled");},()=>{SetTestText("noscroll");});
  4. grdJournals.ScrollIntoViewAsync(grdJournals.Items[0],grdJournals.Columns["Date"], a=>{SetTestText("scrolled");},()=>{SetTestText("noscroll");});

In none of these cases could I get the grid to scroll. Considering that I cleaned out my own modifications, I doubt it's an issue with MoveNext, but watch this space. I'll run a quick trial based on your suggestion.







0
christina noel
Top achievements
Rank 1
answered on 22 Dec 2011, 09:56 PM
I can't figure out what commands I need in the KeyboardCommandBehavior, especially since the default behavior of MoveNext (when ColumnVirtualization is off) is exactly what I want. I WANT the first item of the next row to be the next item. I just want the grid to SCROLL to it, and it's not, no matter which settings I try.

Although, using the KeyboardCommandProvider is going to make some of the code less confusing, because I can add BeginInsert() when tabbing off the end of the last row. I appreciate the idea!

--Christistina
0
Ivan Ivanov
Telerik team
answered on 27 Dec 2011, 07:48 AM
Hello,

Unfortunately it is very difficult for us to recreate your scenario on our side, while having only limited information about it. We would highly appreciate a simple project that separates the navigation related logic that reproduces this behavior, so that we could implement your requirements and send it back to you. Please excuse us for the inconvenience. 

Greetings,
Ivan Ivanov
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
christina noel
Top achievements
Rank 1
answered on 28 Dec 2011, 03:14 PM
I couldn't reproduce this in a sample project. In the process of figuring out why I couldn't, I figured out that when I remove the theme, the scrolling starts working. It turns out that we are NOT using the Office Blue theme. Instead we are using a copy of that theme that we modify when we need a control to behave or look a little differently. Apparently there is a change in our copy of the radgridview that is breaking scrolling. I'm still looking through the changes that we made to try to figure out what's causing the break and how to repair it without altering whatever display or functionality change was apparently needed elsewhere.

Thank you so much for your assistance!

--Christina
0
Vanya Pavlova
Telerik team
answered on 28 Dec 2011, 04:58 PM
Hello,

 
Without small repro project it would be hard to determine what might be causing this behavior. 
Can you verify that using our built-in themes (not only the default one-Office_Black) the scrolling is still the same as it is in your custom project with this custom theme? 



All the best,
Vanya Pavlova
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
christina noel
Top achievements
Rank 1
answered on 28 Dec 2011, 06:20 PM
I can confirm that scrolling is working using OfficeBlue and Transparent (and the default OfficeBlack).

The source of the problem is that the content of the GridViewScrollViewer in our copy of the theme was changed from:
<grid:GridViewVirtualizingPanel x:Name="PART_GridViewVirtualizingPanel"  />
to:
<Grid >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <grid:GridViewVirtualizingPanel x:Name="PART_GridViewVirtualizingPanel"  Visibility="{Binding Visibility, ElementName=otherContent, Converter={StaticResource InvertVisibilityConverter}}" />
    <ContentPresenter x:Name="otherContent" Style="{TemplateBinding ItemContainerStyle}" Content="{TemplateBinding ItemsSource}" Width="{Binding ViewportWidth, ElementName=PART_ItemsScrollViewer}"/>
</Grid>

The purpose of the content presenter was to allow us to hide the grid and instead show a tileview by overriding the ItemContainerStyle. I have managed to resolve the problem by making the width of the defined grid column be "Auto" instead of "*", and have gotten scrolling to work in my grid now without seeming to have corrupted the tileview functionality. I'm sorry to have bothered you with something that was caused by our own buried mistake!

This issue is now resolved.

--Christina

Tags
GridView
Asked by
christina noel
Top achievements
Rank 1
Answers by
Ivan Ivanov
Telerik team
christina noel
Top achievements
Rank 1
Vanya Pavlova
Telerik team
Share this question
or