Repro-steps:
Expected behavior:
Observed behavior:
Please observe that Grid.UserAddedRow is not handled, but since we cannot even see the AddNewRow, it is not required for this bug.
public partial class TestForm: Form
{
private readonly DataView _view;
public TestForm()
{
InitializeComponent();
_view = new DataView(LoadTable(true));
_grid.ColumnCount = _view.Table.Columns.Count;
_grid.RowCount = _view.Count;
_grid.AllowAddNewRow = true;
_grid.SelectionMode = VirtualGridSelectionMode.FullRowSelect;
}
static private DataTable LoadTable(bool fill)
{
var table = new DataTable();
table.Columns.Add("Number", typeof(int));
if (fill)
for(int i = 0; i < 20; i++)
table.Rows.Add(i);
return table;
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this._grid = new Telerik.WinControls.UI.RadVirtualGrid();
((System.ComponentModel.ISupportInitialize)(this._grid)).BeginInit();
this.SuspendLayout();
//
// _grid
//
this._grid.Dock = System.Windows.Forms.DockStyle.Fill;
this._grid.Location = new System.Drawing.Point(0, 0);
this._grid.MultiSelect = true;
this._grid.Name = "_grid";
this._grid.SelectionMode = Telerik.WinControls.UI.VirtualGridSelectionMode.FullRowSelect;
this._grid.Size = new System.Drawing.Size(800, 450);
this._grid.TabIndex = 0;
this._grid.CellValueNeeded += new Telerik.WinControls.UI.VirtualGridCellValueNeededEventHandler(this._grid_CellValueNeeded);
this._grid.UserDeletedRow += new Telerik.WinControls.UI.VirtualGridRowsEventHandler(this._grid_UserDeletedRow);
//
// TestForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this._grid);
this.Name = "TestForm";
this.Text = "TestForm";
((System.ComponentModel.ISupportInitialize)(this._grid)).EndInit();
this.ResumeLayout(false);
}
#endregion
private Telerik.WinControls.UI.RadVirtualGrid _grid;
private void _grid_CellValueNeeded(object sender, Telerik.WinControls.UI.VirtualGridCellValueNeededEventArgs e)
{
if (e.ColumnIndex < 0)
return;
if (e.RowIndex < 0)
{
e.FieldName = _view.Table.Columns[e.ColumnIndex].ColumnName;
if (e.RowIndex == RadVirtualGrid.HeaderRowIndex)
e.Value = e.FieldName;
}
else if (e.RowIndex < _view.Count)
{
e.Value = _view[e.RowIndex][e.ColumnIndex];
}
}
private void _grid_UserDeletedRow(object sender, Telerik.WinControls.UI.VirtualGridRowsEventArgs e)
{
var rowIndexes = e.RowIndices.Distinct().OrderByDescending(i => i).ToList(); // Off topic: I have seen duplicate row indexes in this row collection. And unsorted. Is that by design?
if (rowIndexes.Count == _view.Count)
{
_view.Table.Rows.Clear();
}
else
{
foreach(var index in rowIndexes)
_view[index].Delete();
}
_grid.RowCount = _view.Count;
}
}
Pin columns cut the content of custom cells.
In this case, we filter a column by typing in a filter cell. If we have a horizontal scroll move the filter cell out of the view and then go back to it and try to change the value of the filter cell, the editor has an empty string.
This behavior is observed when the VisualStudio2022Light theme is applied. For example, this is not observed in the Fluent theme.
The problem also occurs, if you just start the form. For example, on 175% (without drag).
Elements in the child grid that are outside of the parent bounds are not active. This means that you can't resize the column, edit, filter, sort or use any other build-in behavior.
The horizontal scrollbar should not appear on top of the data row.
When the control is populated with hierarchy data, the current arrow icon and the expander icon overlap each other. This is observed when you click on a row.
As a workaround, we can increase the size of the indent column to leave enough space for both icons.
this.radVirtualGrid1.TableElement.IndentColumnWidth = 40;
Then we can move the current row arrow icon to the left (or right, depending on your requirement) in the CellFormatting event handler of the control.
private void radVirtualGrid1_CellFormatting(object sender, VirtualGridCellElementEventArgs e)
{
if (e.CellElement is VirtualGridIndentCellElement)
{
var indentCell = e.CellElement as VirtualGridIndentCellElement;
indentCell.ImageLayout = ImageLayout.None;
indentCell.ImageAlignment = ContentAlignment.MiddleLeft;
}
}
Currently, this behavior is available for RadGridView and the parent row becomes current/selected after expanding. Please refer to the attached gif file for RadGridView and the missing functionality for RadVirtualGrid.
Repro steps:
Observed behavior:
Expected behavior:
Observation / suggestion:
RadVirtualGrid.Selection.HasSelection (VirtualGridSelection.HasSelection) or is never false.
RadVirtualGrid grid = new RadVirtualGrid();
var hasSelection1 = grid.Selection.HasSelection;
_grid.Selection.ClearSelection();
var hasSelection2 = grid.Selection.HasSelection;
After initializing the grid, and not loading anything, HasSelection is true, while nothing is selected.
After clearing the selection, HasSelection remains true.
This property is used in your own code as a pretest for some operations. (Like Copy or Cut).
Am I interpreting this property the wrong way?
Repro steps:
Exception:
Message : Object reference not set to an instance of an object.
Type : System.NullReferenceException
Source : Telerik.WinControls.GridView
Stack trace : Telerik.WinControls.UI.RadVirtualGridElement.CopyToClipboard(Int32 startRow, Int32 startColumn, Int32 endRow, Int32 endColumn, VirtualGridViewInfo viewInfo, Boolean selectedOnly, Boolean cut)
Telerik.WinControls.UI.RadVirtualGridElement.CopySelection()
Turien.Windows.Forms.Telerik.VirtualGrid.VirtualGridViewPlus.RadVirtualGridElementPlus.CopySelection()
Turien.Windows.Forms.Telerik.VirtualGrid.VirtualGridViewPlus.VirtualGridInputBehaviorPlus.HandleUnhandledKeys(KeyEventArgs keys)
Telerik.WinControls.UI.VirtualGridInputBehavior.HandleKeyDown(KeyEventArgs args)
Telerik.WinControls.UI.RadVirtualGrid.OnKeyDown(KeyEventArgs e)
System.Windows.Forms.Control.ProcessKeyEventArgs(Message& m)
System.Windows.Forms.Control.ProcessKeyMessage(Message& m)
System.Windows.Forms.Control.WmKeyChar(Message& m)
System.Windows.Forms.Control.WndProc(Message& m)
System.Windows.Forms.ScrollableControl.WndProc(Message& m)
Telerik.WinControls.RadControl.WndProc(Message& m)
System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
System.Windows.Forms.Application.Run(Form mainForm)
Turien.Schade.PremiumCalculator.LookupTableManager.Program.Main()
When copying to from the RadVirtualGrid to the clipboard, the HTML format is not supported.
I was thinking about creating a feature request, but I really think this is a bug, because:
Please, implement the support for HTML.
When I use the Copy method in the RadGridView, the content is copied to the clipboard in multiple formats. Each format can be cancelled. If a format is cancelled it is not even serialized into the DataObject. This way a programmer can replace the copy-routine for that format with his own.
When I do the same with RadVirtualGrid, and I only want to copy format CSV and I want to cancel the rest, nothing is copied to the clipboard. The funny thing is, inspecting the code, the data is always serialized to the DataObject BEFORE the event is fired to find out if that action is needed. This is a performance penalty.
So these two behaviors are inconsistent. It is also inconsistent the the Paste-operations of both grids.
Current code:
public void CopyToClipboard(
int startRow,
int startColumn,
int endRow,
int endColumn,
VirtualGridViewInfo viewInfo,
bool selectedOnly,
bool cut)
{
DataObject dataObject = new DataObject();
string data1 = this.ProcessContent(DataFormats.Text, startRow, startColumn, endRow, endColumn, viewInfo, selectedOnly, cut);
dataObject.SetData(DataFormats.UnicodeText, false, (object) data1);
VirtualGridClipboardEventArgs args1 = new VirtualGridClipboardEventArgs(false, DataFormats.UnicodeText, dataObject, this.CurrentCell.ViewInfo);
this.OnCopying(args1);
if (args1.Cancel)
return;
dataObject.SetData(DataFormats.Text, false, (object) data1);
VirtualGridClipboardEventArgs args2 = new VirtualGridClipboardEventArgs(false, DataFormats.Text, dataObject, this.CurrentCell.ViewInfo);
this.OnCopying(args2);
if (args2.Cancel)
return;
string data2 = this.ProcessContent(DataFormats.CommaSeparatedValue, startRow, startColumn, endRow, endColumn, viewInfo, selectedOnly, cut);
dataObject.SetData(DataFormats.CommaSeparatedValue, false, (object) data2);
VirtualGridClipboardEventArgs args3 = new VirtualGridClipboardEventArgs(false, DataFormats.CommaSeparatedValue, dataObject, this.CurrentCell.ViewInfo);
this.OnCopying(args3);
if (args3.Cancel)
return;
Clipboard.SetDataObject((object) dataObject);
}
public void CopyToClipboard(
int startRow,
int startColumn,
int endRow,
int endColumn,
VirtualGridViewInfo viewInfo,
bool selectedOnly,
bool cut)
{
DataObject dataObject = new DataObject();
VirtualGridClipboardEventArgs eventArgs = new VirtualGridClipboardEventArgs(false, DataFormats.UnicodeText, dataObject, CurrentCell.ViewInfo);
OnCopying(eventArgs);
bool useText = !eventArgs.Cancel;
eventArgs = new VirtualGridClipboardEventArgs(false, DataFormats.UnicodeText, dataObject, CurrentCell.ViewInfo);
OnCopying(eventArgs);
bool useUnicodeText = !eventArgs.Cancel;
if (useText || useUnicodeText)
{
string text = __instance.ProcessContent(DataFormats.Text, startRow, startColumn, endRow, endColumn, viewInfo, cut);
if (useText)
dataObject.SetData(DataFormats.Text, false, text);
if (useUnicodeText)
dataObject.SetData(DataFormats.UnicodeText, false, text);
}
eventArgs = new VirtualGridClipboardEventArgs(false, DataFormats.Text, dataObject, CurrentCell.ViewInfo);
OnCopying(eventArgs);
if (!eventArgs.Cancel)
{
string csv = __instance.ProcessContent(DataFormats.CommaSeparatedValue, startRow, startColumn, endRow, endColumn, viewInfo, selectedOnly, cut);
dataObject.SetData(DataFormats.CommaSeparatedValue, false, csv);
}
if (dataObject.GetFormats().Length > 0)
Clipboard.SetDataObject(dataObject);
}