I miss grouping functionality in VirtualGrid. In my opinion, the following process would be conceivable: 1. user interaction triggers an event - e. g. GroupChanged (similar to FilterChanged). 2. This event determines all available groups and returns them to the VirtualGrid. 3. if the user expand a group > a second event is fired - and returns all matching data rows.
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;
}
}
RadVirtualGrid does not support (nullable) booleans out of the box.
There are several pages to work around this issues, like:
In my humble opinion this should be supported by default. Why?
In my mind I think of how a meeting would have been while designing the RadVirtualGrid.
;-)
Please run the attached sample project and navigate with the left/right arrows as it is demonstrated in the gif file.
Scenario to cover: the user tries to filter the grid not with each entered symbol but when the value in the filter cell is committed (Enter key is pressed) and the editor is closed. The CellValuePushed event is fired only for data cells and the FilterChanged event is fired with each keystroke but not when the editor is closed. A similar scenario is valid for the new row. There is no suitable event for capturing when a certain cell is updated in the new row as well.
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).
I was trying to move the NewRow to the bottom of the RadVirtualGrid. This is also supported by its big brother RadGridView. I have now learned that this is not supported by RadVirtualGrid.
Hereby my request: Please support this!
I've created a Harmony patch (which works for me); it might help you if you decide to support it:
static class MoveNewRowToBottom
{
[HarmonyPatch(typeof(VirtualGridTableElement), "InvalidatePinnedRows")]
static class VirtualGridTableElement_InvalidatePinnedRows
{
static private bool _isInvalidating;
static private bool Prefix(VirtualGridTableElement __instance)
{
if (_isInvalidating)
return false;
_isInvalidating = true;
__instance.ViewElement.TopPinnedRows.DisposeChildren();
__instance.ViewElement.BottomPinnedRows.DisposeChildren();
var viewInfo = __instance.ViewInfo;
var rowsViewState = __instance.RowsViewState;
var topPinnedItems = rowsViewState.TopPinnedItems;
var bottomPinnedItems = rowsViewState.BottomPinnedItems;
if (viewInfo.ShowFilterRow)
if (!topPinnedItems.Contains(RadVirtualGrid.FilterRowIndex) && !bottomPinnedItems.Contains(RadVirtualGrid.FilterRowIndex))
rowsViewState.SetPinPosition(RadVirtualGrid.FilterRowIndex, PinnedRowPosition.Top);
if (viewInfo.ShowNewRow)
if (!topPinnedItems.Contains(RadVirtualGrid.NewRowIndex) && !bottomPinnedItems.Contains(RadVirtualGrid.NewRowIndex))
rowsViewState.SetPinPosition(RadVirtualGrid.NewRowIndex, PinnedRowPosition.Top);
if (viewInfo.ShowHeaderRow)
if (!topPinnedItems.Contains(RadVirtualGrid.HeaderRowIndex) && !bottomPinnedItems.Contains(RadVirtualGrid.HeaderRowIndex))
rowsViewState.SetPinPosition(RadVirtualGrid.HeaderRowIndex, PinnedRowPosition.Top);
var elementProvider = __instance.RowScroller.ElementProvider;
var topPinnedRows = __instance.ViewElement.TopPinnedRows;
foreach (int topPinnedRow in topPinnedItems.SortTopRowIndexes())
{
VirtualGridRowElement pinnedRow = (VirtualGridRowElement)elementProvider.GetElement(topPinnedRow, null);
topPinnedRows.Children.Add(pinnedRow);
pinnedRow.Attach(topPinnedRow, null);
}
var bottomPinnedRows = __instance.ViewElement.BottomPinnedRows;
foreach (int bottomPinnedRow in bottomPinnedItems.SortBottomRowIndexes())
{
VirtualGridRowElement pinnedRow = (VirtualGridRowElement)elementProvider.GetElement(bottomPinnedRow, null);
bottomPinnedRows.Children.Add(pinnedRow);
pinnedRow.Attach(bottomPinnedRow, null);
}
_isInvalidating = false;
return false;
}
}
static private IEnumerable<int> SortTopRowIndexes(this ReadOnlyCollection<int> topRowIndexes)
{
var specialRowIndex = topRowIndexes.Where(index => index < 0).ToList();
if (specialRowIndex.Contains(RadVirtualGrid.HeaderRowIndex))
yield return RadVirtualGrid.HeaderRowIndex;
if (specialRowIndex.Contains(RadVirtualGrid.NewRowIndex))
yield return RadVirtualGrid.NewRowIndex;
if (specialRowIndex.Contains(RadVirtualGrid.FilterRowIndex))
yield return RadVirtualGrid.FilterRowIndex;
foreach (var index in topRowIndexes.Where(index => index >= 0))
yield return index;
}
static private IEnumerable<int> SortBottomRowIndexes(this ReadOnlyCollection<int> bottomRowIndexes)
{
foreach (var index in bottomRowIndexes.Where(index => index >= 0))
yield return index;
var specialRowIndex = bottomRowIndexes.Where(index => index < 0).ToList();
if (specialRowIndex.Contains(RadVirtualGrid.FilterRowIndex))
yield return RadVirtualGrid.FilterRowIndex;
if (specialRowIndex.Contains(RadVirtualGrid.NewRowIndex))
yield return RadVirtualGrid.NewRowIndex;
if (specialRowIndex.Contains(RadVirtualGrid.HeaderRowIndex))
yield return RadVirtualGrid.HeaderRowIndex;
}
}
RadVirtualGridElement.Paste does not support pasting into new rows.
I want to override RadVirtualGridElement.Paste to allow to to paste into new rows. Except when I do so, the methods to retrieve information from the clipboard (GetHtmlData/GetTextData/GetCsvData ) are private.
So now I have one request, two solutions:
Hello, we have found another small bug of the RadVirtualGrid control.
When paging is enabled on child view, one of the component of the paging panel overlap whit is parent.
I attach source code and screenshot.
Thanks in advance.
To reproduce: please refer to the attached gif file. The CellClick is not fired for the child rows that belong to columns that exceed the width of the parent template. Workaround: set the AutoSizeColumnsMode property to Fill. this.radVirtualGrid1.AutoSizeColumnsMode = Telerik.WinControls.UI.VirtualGridAutoSizeColumnsMode.Fill;
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.