Completed
Last Updated: 27 May 2015 06:51 by ADMIN
ADMIN
Jack
Created on: 05 Jul 2012 00:49
Category: GridView
Type: Bug Report
4
FIX. RadGridView - non-visible selected cells disappear when selecting multiple cells with the mouse.
1. Create a new project with RadGridView and set MultiSelect to true and SelectionMode to CellSelect.
2. Run the project.
3. Use the mouse to select some cells and scroll down while selecting.
4. Remove some cells from the selection.
5. Scroll with the scrollbar up to the first selected cells. You will see that all previously selected cells which are not visible are not selected.

Workaround:
Use the following custom behavior:
public class MyGridRowBehavior : GridDataRowBehavior
{
    private FieldInfo oldCurrentLocationFieldInfo;
    private Point oldCurrentLocation
    {
        get
        {
            if (this.oldCurrentLocationFieldInfo == null)
            {
                this.oldCurrentLocationFieldInfo = typeof(GridRowBehavior).GetField("oldCurrentLocation", BindingFlags.Instance | BindingFlags.NonPublic);
            }

            return (Point)this.oldCurrentLocationFieldInfo.GetValue(this);
        }
        set
        {
            this.oldCurrentLocationFieldInfo.SetValue(this, value);
        }
    }

    private MethodInfo selectIntersectedCellsMethodInfo;
    private delegate void SelectIntersectedCellsDelegate(RadElementCollection rows, bool isProcessedShiftOrControl);
    private SelectIntersectedCellsDelegate SelectIntersectedCellsCore;
    private void SelectIntersectedCells(RadElementCollection rows, bool isProcessedShiftOrControl)
    {
        if (this.selectIntersectedCellsMethodInfo == null)
        {
            this.selectIntersectedCellsMethodInfo = typeof(GridRowBehavior).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).First(x => x.Name == "SelectIntersectedCells" && x.GetParameters().Length == 2);
            this.SelectIntersectedCellsCore = (SelectIntersectedCellsDelegate)Delegate.CreateDelegate(typeof(SelectIntersectedCellsDelegate), this, this.selectIntersectedCellsMethodInfo);
        }

        this.SelectIntersectedCellsCore(rows, isProcessedShiftOrControl);
    }

    private MethodInfo selectIntersectedRowsMethodInfo;
    private delegate bool SelectIntersectedRowsDelegate(RadElementCollection rows);
    private SelectIntersectedRowsDelegate SelectIntersectedRowsCore;
    private bool SelectIntersectedRows(RadElementCollection rows)
    {
        if (this.selectIntersectedRowsMethodInfo == null)
        {
            this.selectIntersectedRowsMethodInfo = typeof(GridRowBehavior).GetMethod("SelectIntersectedRows", BindingFlags.Instance | BindingFlags.NonPublic);
            this.SelectIntersectedRowsCore = (SelectIntersectedRowsDelegate)Delegate.CreateDelegate(typeof(SelectIntersectedRowsDelegate), this, this.selectIntersectedRowsMethodInfo);
        }

        return this.SelectIntersectedRowsCore(rows);
    }

    protected override bool ProcessMouseSelection(Point mousePosition, GridCellElement currentCell)
    {
        if (this.RootGridBehavior.LockedBehavior != this)
        {
            this.GridControl.Capture = true;
            this.RootGridBehavior.LockBehavior(this);
        }

        GridCellElement mouseDownCell = this.GetCellAtPoint(this.MouseDownLocation);
        GridCellElement oldCurrentCell = this.GetCellAtPoint(this.oldCurrentLocation);

        bool isValidResizingContext = this.ResizeSelectionRectangle(currentCell, mousePosition);
        bool result = false;

        if (isValidResizingContext && oldCurrentCell != currentCell)
        {
            if (this.MasterTemplate.MultiSelect && !this.GridViewElement.Template.AllowRowReorder)
            {
                if (this.MasterTemplate.SelectionMode == GridViewSelectionMode.FullRowSelect)
                {
                    bool selectedRowsChanged = false;
                    bool isPressedShiftOrControl = (this.IsPressedShift || this.IsPressedControl);

                    GridTableElement tableElement = this.GridViewElement.CurrentView as GridTableElement;
                    RadElementCollection scrollableRows = tableElement.ViewElement.ScrollableRows.Children;
                    RadElementCollection topPinnedRows = tableElement.ViewElement.TopPinnedRows.Children;
                    RadElementCollection bottomPinnedRows = tableElement.ViewElement.BottomPinnedRows.Children;
                    GridViewRowInfo[] selectedRows = this.MasterTemplate.SelectedRows.ToArray();

                    tableElement.BeginUpdate();

                    int oldSelectedRows = this.MasterTemplate.SelectedRows.Count;

                    if (!isPressedShiftOrControl)
                    {
                        for (int i = selectedRows.Length - 1; i >= 0; i--)
                        {
                            GridViewRowInfo rowInfo = selectedRows[i];
                            GridRowElement rowElement = tableElement.GetRowElement(rowInfo);

                            bool select = rowElement != null &&
                                                 rowElement.ControlBoundingRectangle.IntersectsWith(this.GridViewElement.SelectionRectangle);

                            if (select)
                            {
                                rowInfo.IsSelected = true;
                            }

                            if (!rowInfo.IsSelected)
                            {
                                selectedRowsChanged = true;
                            }
                        }
                    }

                    selectedRowsChanged = this.SelectIntersectedRows(topPinnedRows);
                    selectedRowsChanged |= this.SelectIntersectedRows(scrollableRows);
                    selectedRowsChanged |= this.SelectIntersectedRows(bottomPinnedRows);

                    if (oldSelectedRows != this.MasterTemplate.SelectedRows.Count)
                    {
                        selectedRowsChanged = true;
                    }

                    tableElement.EndUpdate(false);
                }
                else
                {
                    GridTableElement tableElement = this.GridViewElement.CurrentView as GridTableElement;

                    if (tableElement == null)
                    {
                        return result;
                    }

                    CancelEventArgs cancelArgs = new CancelEventArgs();
                    this.MasterTemplate.EventDispatcher.RaiseEvent<CancelEventArgs>(EventDispatcher.SelectionChanging, this, cancelArgs);
                    if (cancelArgs.Cancel)
                    {
                        return result;
                    }
                    
                    //Since version Q2 2014 (version 2014.2.617), please use:
                    //GridViewSelectionCancelEventArgs cancelArgs = new GridViewSelectionCancelEventArgs(this.MasterTemplate.CurrentRow, this.MasterTemplate.CurrentColumn);
                    //this.MasterTemplate.EventDispatcher.RaiseEvent<GridViewSelectionCancelEventArgs>(EventDispatcher.SelectionChanging, this, cancelArgs);
                    //if (cancelArgs.Cancel)
                    //{
                    //    return result;
                    //}

                    this.GridViewElement.CurrentView.BeginUpdate();
                    bool isProcessedShiftOrControl = (this.IsPressedShift || this.IsPressedControl);

                    int count = this.MasterTemplate.SelectedCells.Count;
                    RadElementCollection scrollableRows = tableElement.ViewElement.ScrollableRows.Children;
                    RadElementCollection topPinnedRows = tableElement.ViewElement.TopPinnedRows.Children;
                    RadElementCollection bottomPinnedRows = tableElement.ViewElement.BottomPinnedRows.Children;

                    this.SelectIntersectedCells(scrollableRows, isProcessedShiftOrControl);
                    this.SelectIntersectedCells(topPinnedRows, isProcessedShiftOrControl);
                    this.SelectIntersectedCells(bottomPinnedRows, isProcessedShiftOrControl);

                    bool notifyUpdates = true;

                    if (isProcessedShiftOrControl)
                    {
                        notifyUpdates = count != this.MasterTemplate.SelectedCells.Count;
                    }

                    this.GridViewElement.CurrentView.EndUpdate(false);

                    this.GridViewElement.Invalidate();
                }

                result = true;
            }

            result = false;
        }

        this.oldCurrentLocation = mousePosition;
        return result;
    }
}


Register the new behavior as follows:

BaseGridBehavior behavior = (BaseGridBehavior)this.radGridView1.GridBehavior;
behavior.UnregisterBehavior(typeof(GridViewDataRowInfo));
behavior.RegisterBehavior(typeof(GridViewDataRowInfo), new MyGridRowBehavior());
3 comments
ADMIN
Dess | Tech Support Engineer, Principal
Posted on: 30 Mar 2015 14:58
Hello Tony, 

you can refer to the following forum thread: http://www.telerik.com/forums/multiselect-for-the-radgridview
tony
Posted on: 26 Mar 2015 08:50
Issue still exist even if I use Workaround code.
Attached Files:
Jesse Dyck
Posted on: 04 Jun 2013 11:12
Issue also exists when Selection Mode is set to "FullRowSelect"