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

VirtualGrid row of custom cells

7 Answers 153 Views
VirtualGrid
This is a migrated thread and some comments may be shown as answers.
Yuri
Top achievements
Rank 1
Yuri asked on 23 Jan 2019, 01:49 PM

Hi,

I'm trying to create row of check boxes. To do that I created custom cell element as described in the topic https://docs.telerik.com/devtools/winforms/controls/virtualgrid/cells/creating-custom-cells.

But after form resizing custom cells are displayed in wrong row.

Please find screenshot attached.

Is it a working way to implement row of custom cells in VirtualGrid?

Thank you in advance.

7 Answers, 1 is accepted

Sort by
0
Hristo
Telerik team
answered on 24 Jan 2019, 12:04 PM
Hello Yuri,

The UI building the RadVirtualGrid control is also virtualized, basically meaning that the visual elements are reused while scrolling. The screenshots indicate that custom cell is being used in a column in which it is not intended. Can you please check the IsCompatible method in the custom cell class in your project and make sure that it returning true only for the desired column. In case the issue persists, please share a code snippet demonstrating the result on your end so that I can test it.

I hope this will help.

Regards,
Hristo
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Yuri
Top achievements
Rank 1
answered on 24 Jan 2019, 01:45 PM

Hi Hristo,

Thank you for your reply.

I took a look on IsCompatible method. And it works fine for me. But issue still exists.

I would like to share a code snippet with you.

//Custom cell implementation
public class VirtualGridCheckBoxCellElement : VirtualGridCellElement
{
    public event IsCompatibleEventHandler IsCompatibleCell;
 
    protected override void CreateChildElements()
    {
        base.CreateChildElements();
 
        checkBox = new RadCheckBoxElement();
        Children.Add(checkBox);
    }
 
    public override bool IsCompatible(int data, object context)
    {
        if (context is VirtualGridRowElement rowElement)
        {
            var args = new IsCompatibleEventArgs(data, rowElement);
            IsCompatibleCell?.Invoke(this, args);
             
            return args.IsCompatible;
        }
 
        return false;
    }
 
    private RadCheckBoxElement checkBox;
}
 
public delegate void IsCompatibleEventHandler(object caller, IsCompatibleEventArgs args);
 
public class IsCompatibleEventArgs : EventArgs
{
    public int ColumnIndex { get; }
    public VirtualGridRowElement RowElement { get; }
    public bool IsCompatible { get; set; }
 
    internal IsCompatibleEventArgs(int columnIndex, VirtualGridRowElement rowElement)
    {
        ColumnIndex = columnIndex;
        RowElement = rowElement;
    }
}
//usage
private void VirtualGrid_CreateCellElement(object sender, VirtualGridCreateCellEventArgs e)
{
    if (IsCheckBoxCompatibleCell(e.RowIndex, e.ColumnIndex))
    {
        var checkBoxCellElement = new VirtualGridCheckBoxCellElement();
 
        checkBoxCellElement.IsCompatibleCell += (o, args) =>
        {
            args.IsCompatible = IsCheckBoxCompatibleCell(args.RowElement.RowIndex, args.ColumnIndex);
        };
 
        e.CellElement = checkBoxCellElement;
    }
}
 
public bool IsCheckBoxCompatibleCell(int rowIndex, int columnIndex)
{
    return columnIndex >= 0 && rowIndex == 33;
}

 

Used version of controls is 2017.1.221.40. Maybe this is a reason...

Thank you, Yuri

0
Accepted
Hristo
Telerik team
answered on 25 Jan 2019, 01:25 PM
Hello Yuri,

Looking at the code snippet and the screenshot, it appears that you are trying to create a custom cell only for a particular row and column in the grid. This way the grid ends up with different cells located in the same column. Because of reusing the elements, this leads to the described behavior. Please note that this is not supported and if you need custom cells, you will need to use them for the entire column. Then the IsCompatible method should only return true if the column index is the one you have specified and the row is data row.

As a possible solution, you can try creating a custom cell having different elements in it. This way you will be able to display one element inside the cell for some rows and other elements for other rows. I am attaching my test project demonstrating the suggested approach as well as a short video showing the result on my end.

Regards,
Hristo
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Yuri
Top achievements
Rank 1
answered on 28 Jan 2019, 02:08 PM

Hi Hristo,

Thank you for you reply.

I have tried your solution, but it slows down my grid where commonly displayed over 200 columns.
And I finished with another solution. It works for me fine. 

I would like to share it. Could you please take a look and answer if you see something wrong?

private void virtualGrid_CellFormatting(object sender, VirtualGridCellElementEventArgs e)
{
    if (e.CellElement.RowIndex < 0 || e.CellElement.RowIndex >= virtualGrid.RowCount || e.CellElement is VirtualGridIndentCellElement)
    {
        return;
    }
     
    if (e.CellElement.Value is bool)
    {
        MakeCheckBoxCell(e.CellElement);
    }
    else
    {
        RestoreNormalCell(e.CellElement);
    }
}
 
private void MakeCheckBoxCell(VirtualGridCellElement cellElement)
{
    if (cellElement.Children.Any())
    {
        cellElement.Children.Clear();
    }
     
    cellElement.Children.Add(InitCheckBox(cellElement));
    cellElement.DrawText = false;
}
 
private void RestoreNormalCell(VirtualGridCellElement cellElement)
{
    cellElement.Children.Clear();
    cellElement.ResetValue(LightVisualElement.DrawTextProperty, ValueResetFlags.Local);
}
 
private RadCheckBoxElement InitCheckBox(VirtualGridCellElement cellElement)
{
    var newCheckBoxElement = new RadCheckBoxElement
    {
        Checked = (bool) cellElement.Value,
        CheckAlignment = ContentAlignment.MiddleCenter
    };
 
    newCheckBoxElement.CheckStateChanged += (o, e) =>
    {
        timetableGrid.VirtualGridElement.SetCellValue(newCheckBoxElement.Checked, cellElement.RowIndex,
            cellElement.ColumnIndex, cellElement.ViewInfo);
 
        timetableGrid.SelectCell(cellElement.RowIndex, cellElement.ColumnIndex);
    }
 
    return newCheckBoxElement;
}
0
Accepted
Hristo
Telerik team
answered on 29 Jan 2019, 12:16 PM
Hello Yuri,

Generally speaking, you need to be careful when instantiating objects in the CellFormating event. This event will be raised numerous times while running the application and initializing objects in it may increase the consumed memory. Otherwise, I see no other issues with your approach. You can consider caching the elements so that new RadCheckBoxElement objects are created for new rows which are raising the formatting event. In order to update the toggle state of the checkbox, I also had to use a flag and suspend the formatting. Please check my code snippet below: 
bool suspenFormatting;
Dictionary<int, RadCheckBoxElement> checkElements = new Dictionary<int, RadCheckBoxElement>();
 
private void RadVirtualGrid1_CellFormatting(object sender, VirtualGridCellElementEventArgs e)
{
    if (this.suspenFormatting || e.CellElement.RowIndex < 0 || e.CellElement.RowIndex >= this.radVirtualGrid1.RowCount || e.CellElement is VirtualGridIndentCellElement)
    {
        return;
    }
 
    if (e.CellElement.Value is bool)
    {
        MakeCheckBoxCell(e.CellElement);
    }
    else
    {
        RestoreNormalCell(e.CellElement);
    }
}
 
private void MakeCheckBoxCell(VirtualGridCellElement cellElement)
{
    if (cellElement.Children.Any())
    {
        cellElement.Children.Clear();
    }
 
    cellElement.Children.Add(InitCheckBox(cellElement));
    cellElement.DrawText = false;
}
 
private void RestoreNormalCell(VirtualGridCellElement cellElement)
{
    cellElement.Children.Clear();
    cellElement.ResetValue(LightVisualElement.DrawTextProperty, ValueResetFlags.Local);
}
 
private RadCheckBoxElement InitCheckBox(VirtualGridCellElement cellElement)
{
    RadCheckBoxElement checkElement = null;
    if (!checkElements.ContainsKey(cellElement.RowIndex))
    {
        checkElement = new RadCheckBoxElement();
        checkElements.Add(cellElement.RowIndex, checkElement);
    }
    else
    {
        checkElement = checkElements[cellElement.RowIndex];
    }
 
    checkElement.CheckStateChanged -= checkElement_CheckStateChanged;
    checkElement.Checked = (bool)cellElement.Value;
    checkElement.CheckAlignment = ContentAlignment.MiddleCenter;
    checkElement.CheckStateChanged += checkElement_CheckStateChanged;
 
    return checkElement;
}
 
private void checkElement_CheckStateChanged(object sender, EventArgs e)
{
    this.suspenFormatting = true;
    RadCheckBoxElement checkElement = (RadCheckBoxElement)sender;
    VirtualGridCellElement cellElement = checkElement.Parent as VirtualGridCellElement;
 
    this.radVirtualGrid1.VirtualGridElement.SetCellValue(checkElement.Checked, cellElement.RowIndex,
            cellElement.ColumnIndex, cellElement.ViewInfo);
 
    this.radVirtualGrid1.SelectCell(cellElement.RowIndex, cellElement.ColumnIndex);
 
    this.suspenFormatting = false;
}

I hope this will help. Let me know if you need further assistance.

Regards,
Hristo
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Yuri
Top achievements
Rank 1
answered on 30 Jan 2019, 08:14 AM

Hi Hristo,

Thank you very much for your reply, it worka for me perfect!

With the best regards, Yuri.

0
Hristo
Telerik team
answered on 30 Jan 2019, 11:32 AM
Hello Yuri,

Thank you for the update. I am glad that the discussed approach is working well on your end. Let me know if you need further assistance.

Regards,
Hristo
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
VirtualGrid
Asked by
Yuri
Top achievements
Rank 1
Answers by
Hristo
Telerik team
Yuri
Top achievements
Rank 1
Share this question
or