Unplanned
Last Updated: 13 Feb 2023 07:32 by ADMIN
Martin
Created on: 27 Jan 2023 12:29
Category: VirtualGrid
Type: Bug Report
2
RadVirtualGrid does not show "AddNewRow" when RowCount == 0.

Repro-steps:

  1. Use the code beneath.
  2. Run this form.
  3. 20 records are shown, the "AddNewRow" is shown.
  4. Select all records.
  5. Press <delete>
  6. 0 records are shown (as expected), the "AddNewRow" is invisible (unexpected).
  7. Close the program.
  8. Modify LoadTable(true) to LoadTable(false). Records will not be created..
  9. Run this form.
  10. 0 records are shown (as expected), the "AddNewRow" is invisible (unexpected).

Expected behavior:

  • Even when the dataTable or view has no rows, we should still be able to add new rows.

Observed behavior:

  • When datatable/view is empty, no new records are allowed to enter.

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;
		}
	}

6 comments
ADMIN
Dess | Tech Support Engineer, Principal
Posted on: 13 Feb 2023 07:32

Hi, Martin,

After discussing this with the team, I have approved this item in order to provide functionality for showing the column headers without any data rows available in RadVirtualGrid. Thus, the user will be allowed to fill data in an empty grid. Currently, you need to set the RowCount property at least to 1 to show the column headers, filter row, etc.

The SetColumnDataType method is usually used to determine what editor type to be activated when a cell enters edit mode in RadVirtualGrid since there are no actual columns with a specific type that are added to the virtual grid. 

I have also updated your Telerik points.

Make sure that you follow this item in order to get notified once any status changes occur.

Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Martin
Posted on: 06 Feb 2023 14:00

Addition: Of course there is SetColumnDataType to set the datatype explicitly. I already used this one. This function is, if you look at the design, a bit of a workaround. The CellValueNeeded asks for values and the values are used to determine the type of that column. But sometimes a whole column can contain NULL which will result in an unknown column type. I suspect that SetColumnDataType is introduced to prevent / override that bevahior... but should that information not have been asked by the RadVirtualGrid when ColumnCount was modified (like I suggested in my previous reaction).

Anyway... Back to the subject. When RowCount = 0, ColumnCount > 0 and all column types are known, would it be possible to allow the user to enter a first new row? I think it would be helpfull when building a new table.

Martin
Posted on: 06 Feb 2023 11:37

Hi Dess,

You asked what we are trying to achieve. Very basically we are creating an application which looks a bit like SQL-server-Management-Studio (SSMS). With this application we can:

  1. Create, design and delete tables.
  2. Modify the data inside those tables (for this we use the .NET DataTable+DataView).

(Of course the application does much more than this, but that is not relevant right now.)

For the second point we use the RadVirtualGrid. And here is the problem. When a user has created a new datatable, that table will be empty. Right now, the user cannot ever insert a new (first) row into that table.

Secondly, most of the time, new data for certain tables is given to us (by other teams or companies) using Excel. So what a user normally does is: Delete existing records in table => Select record in Excel => Copy these records => Paste these record inside the empty table (which is not possible, since not even an new row can be selected to paste it into).

So far the functional talk, now let's talk technical:

If think that, when RowCount and ColumnCount are both 0, CellValueNeeded should never be called.
But when RowCount = 0 and ColumnCount is X (and X > 0), then CellValueNeeded should at least be called at least X time for the column headers. 

I understand that during creation of filterrows and the new-rows, datatypes are required. And since no datarow is available, RadGridView assumes (?) that this information cannot be retrieved? If think another even is required, something like: ColumnTypeNeeded, ColumnInfoNeeded or ColumnMetaDataNeeded. Metadata is almost always available (in a DataTable => DataColumn, or in an entity (Type => PropertyInfo), even if there is no data available. Maybe you already have an event like this, or another method which I should use?

Thinking about this... I think I have discovered a new bug... But that is for another thread.

 

ADMIN
Dess | Tech Support Engineer, Principal
Posted on: 31 Jan 2023 12:00

Hello, Martin,

The RowCount and ColumnCount properties that RadVirtualGrid offers, control how many rows/columns will be displayed in the grid. If the RowCount property is set to 0, this means that no records will be loaded and the CellValueNeeded event is not expected to be fired. The AllowAddNewRow property doesn't make any difference in this situation since the RadVirtualGrid control will be completely empty and no columns will be shown. This is desired behavior:

In order to show the new row ("Click here to add a new row"), it is necessary to have RowCount > 0. Thus, you will be able to show the column headers, the rest of the system rows like the new and filtering rows and one data row. 

public RadForm1()
{
    InitializeComponent();
 
    this.radVirtualGrid1.RowCount = 1;
    this.radVirtualGrid1.ColumnCount = 5;
    this.radVirtualGrid1.CellValueNeeded += radVirtualGrid1_CellValueNeeded;
}
 
private void radVirtualGrid1_CellValueNeeded(object sender, Telerik.WinControls.UI.VirtualGridCellValueNeededEventArgs e)
{
    if (e.RowIndex == -1 && e.ColumnIndex > -1)
    {
        e.Value = "Column" + e.ColumnIndex;
    }
}

It would be greatly appreciated if you can share with us your concern and what is the exact requirement that you are trying to achieve. Once we get better understanding of the precise case and think about a suitable solution.

Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Martin
Posted on: 27 Jan 2023 13:01

Same behaviour is observed in Visual Studio Designer:

 

Changing RowCount from 0 to 1 and back shows the bug.

 

Martin
Posted on: 27 Jan 2023 12:32
Can you modify the title? This post is about RadVirtualGrid, not RadGridView.