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

GridView > GridViewCommandColumn > RadMenuElement > RadLabelElement > CellFormatting > CellElement > Nightmare!

8 Answers 221 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Mike
Top achievements
Rank 2
Mike asked on 07 Jan 2009, 06:32 PM

Hi Guys,

This issues starts with the following thread, specifically the CellFormatting routine.

http://www.telerik.com/community/forums/winforms/gridview/radmenuitem-in-radgridview-events.aspx

We were able to get the grid to display with the RadMenuElement  and RadLabelElement(s) replacing the standard command button.  It looks very cool and works well until the user starts to have a lot of data in the grid – the grid slows down to a crawl (dude, I am talking major crawl with display issues like you wouldn’t believe).  This makes sense because the CellFormatting event is fired whenever you do anything with the grid.  As referred in this thread:

http://www.telerik.com/community/forums/winforms/gridview/adding-image-to-imagecolumn.aspx

So…  I decided to move this functionality as was suggested, but I ran into another issue.  I continually run up against the CellElement object being NULL.  As found in this thread:

http://www.telerik.com/community/forums/winforms/gridview/cellelement-null.aspx

In this thread you state the CellFormatting event handler “is the only place where the CellElement is surely not null”.  Big problem, since the CellFormatting event is causing the grid to slow down, and it makes no sense to put my functionality here because I only need to draw the RadLabelElement(s) once on databind anyways.

So…  I am stuck.

I have tried to get access to the CellElement in the following events:  DataBindingComplete, and CreateCell with no success.

Where can I get access to the CellElement before the grid renders so I can perform the following code.

This code was pulled from the CellFormatting event.

---------------------------------------------------------

e.CellElement.Children.Clear();
RadMenuElement buttonElement = new RadMenuElement();
buttonElement.Items.Add(new RadMenuItem("view"));
buttonElement.Items.Add(new RadMenuItem("modify"));
buttonElement.Items.Add(new RadMenuItem("release"));
buttonElement.Items.Add(new RadMenuItem("new"));
e.CellElement.Children.Add(buttonElement); 


Many thanks,

~Mike

8 Answers, 1 is accepted

Sort by
0
Mike
Top achievements
Rank 2
answered on 08 Jan 2009, 02:06 PM
Telerik,

I need a response on this issue ASAP.  Our product is 2 days from release to our client and we need either a workaround or the issue resolved before we ship.

Many thanks,
~Mike
0
Nikolay
Telerik team
answered on 08 Jan 2009, 05:55 PM

Hi Mike,

Thank you for the question.

Actually, you should not experience serious performance issues, regarding the code of adding RadMenuItems:

void radGridView1_CellFormatting(object sender, CellFormattingEventArgs e)  
{  
    if (e.CellElement is GridCommandCellElement)  
    {  
        if (e.CellElement.Children[0] is RadButtonElement)  
        {  
            e.CellElement.Children.Clear();  
 
            RadMenuElement buttonElement = new RadMenuElement();  
            buttonElement.Items.Add(new RadMenuItem("view"));  
            buttonElement.Items.Add(new RadMenuItem("modify"));  
            buttonElement.Items.Add(new RadMenuItem("release"));  
            buttonElement.Items.Add(new RadMenuItem("new"));  
            e.CellElement.Children.Add(buttonElement);  
        }  
    }   

Although the CellFormatting event will be fired when you scroll up/down or do another operation, the process of adding the RadMenuElement and its items will be executed just once. After that, there will be no RadButtonElement in the cell and the the body of the 'if' clause will not be processed. The only things that will take place are the two 'if' checks.

Regarding the second forum thread, the case in it regards setting the data for the RadGridView's data cells. It does not regard anything concerning the visual representation of the CellElements. Therefore, my suggestion was to traverse the Rows or Columns collections. By 'implement your logic' acutally I meant the process of assigning the images, but nothing else which may concern using CellElements. Please excuse me if I did not make myself clear. So the result in this case should be:

for (int i = 0; i < this.radGridView1.Rows.Count; i++)  
{  
    this.radGridView1.Rows[i].Cells[3].Value = image; // your image here  

Regarding the third forum post, indeed, you should only use the CellElement which the CellFormattingEventArgs provides. The CellElement is the visual cell representing the underlying data cells. Since RadGridView uses row virtualization, the data cells which are not currently displayed, do not have associated CellElements, so a CellElement of a data cell could be null at some point.

I would suggest another approach that you can use in your case. This approach concerns making your own custom cell type where the RadMenuElement will be added. The logic concering this cell element will be executed just once, so no additional logic will be executed when you scroll in RadGridView or making another UI change. I am attaching a sample project to demonstrate this approach.

I hope this helps. If you continue experiencing issue, please send me a sample project demonstrating them. This will allow me to investigate your case and provide you with assistance for further optimizations if such are possible.

Sincerely yours,

Nikolay
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Mike
Top achievements
Rank 2
answered on 08 Jan 2009, 08:00 PM

Hi Nikolay,

We were using this block of code but had refresh issues with the grid - we hide and show some buttons depending on status listed in the row.  If you add this block of code the buttons don't get added correctly and if you scroll up and down the row loses some buttons (refresh issues??).

if (e.CellElement.Children[0] is RadButtonElement)     
        {     
            e.CellElement.Children.Clear();     
 

In your sample you refer to e.CellElement = cell; in radGridView1_CreateCell, but with my version of the controls (Q3 2008 SP1) I don't have access to e.CellElement in the CreateCell event.

I have posted a video to the ticket I opened regarding this issue.

~Mike
0
Nikolay
Telerik team
answered on 09 Jan 2009, 04:42 PM
Hi Mike,

Regarding the version you are using it is not the latest one (which is Q3 2008 SP1, v.8.1.0.0), but you are using Q1 2008 SP1 (v6.1.0.0). In Q1 2008 SP1, indeed, CellElement does not exist in the CreateCell event handler. Generally, there is a solution in this case, you can use e.CellType. However, in this case you should subscribe to the Click events in the custom cell class, but not in the form:
void radGridView1_CreateCell(object sender, GridViewCreateCellEventArgs e)    
{  
    if (e.Row is GridDataRowElement)  
    {  
        if (e.Column is GridViewDataColumn && ((GridViewDataColumn)e.Column).FieldName == "Menu")  
        {  
            e.CellType = typeof(MenuItemsCellElement);  
        }  
    }  
}  
 

However, in Q3 2008 SP1 e.CellElement exists in the CreateRow event handler and I would strongly recommend updating your application to this latest version since many improvements have been made from Q1 2008 to Q3 2008. In addition, if possible, please send us the code used in your CellFormatting event handler (shown on the video in the ticket), because it will help us to make the necessary optimizations for it quicker.

I am looking forward to your response.

Sincerely yours,
Nikolay
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Mike
Top achievements
Rank 2
answered on 09 Jan 2009, 05:41 PM

Hi Nikolay,

Unfortunately we cannot upgrade to the latest version of the software because we are about to release our application.  Since we use almost all of your WinForm controls in our application there is a major concern that upgrading at this point would possibly introduce new bugs - we cannot take this risk at this time.  During the next phase of the application our intention is to upgrade the RadControls to the lastest version.


Here is the code for the CellFormatting

        private void gvManageDocs_CellFormatting(object sender, CellFormattingEventArgs e)  
        {  
            gvManageDocs.MasterGridViewTemplate.Columns.BeginUpdate();  
            if (e.CellElement is GridDateTimeCellElement)  
            {  
                e.CellElement.FormatString = "{0:yyyy}";  
                DateTime dt = Convert.ToDateTime(e.CellElement.Text);  
                e.CellElement.Text = dt.ToString("d");  
            }  
 
            if (e.CellElement is GridCommandCellElement)  
            {  
                GridViewRowInfo gvrRow = e.CellElement.RowInfo;  
                e.CellElement.Children.Clear();  
                RadMenuElement buttonElement = new RadMenuElement();  
                RadLabelElement lblLabel = new RadLabelElement();  
 
                lblLabel.Text = "View";  
                lblLabel.Click += new EventHandler(lblView_Click);  
                lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
 
                lblLabel.ForeColor = Color.Blue;  
                buttonElement.Items.Add(lblLabel);  
                lblLabel = null;  
 
                //role check                             
                if (blnIsInRole == true)  
                {  
                    if (gvrRow.Cells[2].Value.ToString() != "Released")  
                    {  
                        lblLabel = new RadLabelElement();  
                        lblLabel.Text = "Modify";  
                        lblLabel.Click += new EventHandler(lblModify_Click);  
                        lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                        lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                        lblLabel.ForeColor = Color.Blue;  
                        buttonElement.Items.Add(lblLabel);  
 
                        lblLabel = null;  
 
                        lblLabel = new RadLabelElement();  
                        lblLabel.Text = "Release";  
                        lblLabel.Click += new EventHandler(lblRelease_Click);  
                        lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                        lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                        lblLabel.ForeColor = Color.Blue;  
                        buttonElement.Items.Add(lblLabel);  
                        lblLabel = null;  
 
                        lblLabel = new RadLabelElement();  
                        lblLabel.Text = "Delete";  
                        lblLabel.Click += new EventHandler(lblDelete_Click);  
                        lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                        lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                        lblLabel.ForeColor = Color.Blue;  
                        buttonElement.Items.Add(lblLabel);  
                        lblLabel = null;  
 
                        if (gvrRow.Cells["DocCatName"].Value.ToString() != "Generic" && (gvrRow.Cells["DocTypeName"].Value.ToString() == "Policy" || gvrRow.Cells["DocTypeName"].Value.ToString() == "Endorsement"))  
                        {  
                            lblLabel = new RadLabelElement();  
                            lblLabel.Text = "Validate";  
                            lblLabel.Click += new EventHandler(lblValidate_Click);  
                            lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                            lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                            lblLabel.ForeColor = Color.Blue;  
                            buttonElement.Items.Add(lblLabel);  
                            lblLabel = null;  
                        }  
                    }  
 
                    if (gvrRow.Cells[2].Value.ToString() == "Released" && gvrRow.Cells[7].Value.ToString() == "False")  
                    {  
                        lblLabel = new RadLabelElement();  
                        lblLabel.Text = "Version";  
                        lblLabel.Click += new EventHandler(lblVersion_Click);  
                        lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                        lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                        lblLabel.ForeColor = Color.Blue;  
                        buttonElement.Items.Add(lblLabel);  
                    }  
 
                    if (buttonElement.Items.Count > 1)  
                    {  
                        if (gvrRow.Cells[7].Value.ToString() == "True")  
                        {  
                            //Remove the required items from the button  on the grid                                         
                            SetGridButtons(buttonElement);  
 
                        }  
                    }  
 
                    if (gvrRow.Cells["DocTypeName"].Value.ToString() == "Policy")  
                    {  
                        lblLabel = new RadLabelElement();  
                        lblLabel.Text = "Print/Audit";  
                        lblLabel.Click += new EventHandler(lblPrintAudit_Click);  
                        lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                        lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                        lblLabel.ForeColor = Color.Blue;  
                        buttonElement.Items.Add(lblLabel);  
                    }  
                }  
                else  
                {  
                    //if not "School" !!!!  
                    if (gvrRow.Cells[1].Value.ToString() == "Client")  
                    {  
                        if (gvrRow.Cells[2].Value.ToString() != "Released")  
                        {  
                            lblLabel = new RadLabelElement();  
                            lblLabel.Text = "Modify";  
                            lblLabel.Click += new EventHandler(lblModify_Click);  
                            lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                            lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                            lblLabel.ForeColor = Color.Blue;  
                            buttonElement.Items.Add(lblLabel);  
                            lblLabel = null;  
 
                            lblLabel = new RadLabelElement();  
                            lblLabel.Text = "Release";  
                            lblLabel.Click += new EventHandler(lblRelease_Click);  
                            lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                            lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                            lblLabel.ForeColor = Color.Blue;  
                            buttonElement.Items.Add(lblLabel);  
                            lblLabel = null;  
 
                            lblLabel = new RadLabelElement();  
                            lblLabel.Text = "Delete";  
                            lblLabel.Click += new EventHandler(lblDelete_Click);  
                            lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                            lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                            lblLabel.ForeColor = Color.Blue;  
                            buttonElement.Items.Add(lblLabel);  
                            lblLabel = null;  
                        }  
 
                        if (gvrRow.Cells[2].Value.ToString() == "Released")  
                        {  
                            lblLabel = new RadLabelElement();  
                            lblLabel.Text = "Version";  
                            lblLabel.Click += new EventHandler(lblVersion_Click);  
                            lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                            lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                            lblLabel.ForeColor = Color.Blue;  
                            buttonElement.Items.Add(lblLabel);  
                            lblLabel = null;  
                        }  
 
                        if (gvrRow.Cells["DocTypeName"].Value.ToString() == "Policy")  
                        {  
                            lblLabel = new RadLabelElement();  
                            lblLabel.Text = "Print/Audit";  
                            lblLabel.Click += new EventHandler(lblPrintAudit_Click);  
                            lblLabel.MouseLeave += new EventHandler(lblLabel_MouseLeave);  
                            lblLabel.MouseEnter += new EventHandler(lblLabel_MouseEnter);  
                            lblLabel.ForeColor = Color.Blue;  
                            buttonElement.Items.Add(lblLabel);  
                            lblLabel = null;  
                        }  
                    }  
                    SetGridButtons(buttonElement);  
                }  
 
                e.CellElement.Children.Add(buttonElement);  
                gvManageDocs.MasterGridViewTemplate.Columns.EndUpdate();  
            }  
        }  
 

So my only solution is to create a custom column?  Can we get around the display issue when using

if (e.CellElement.Children[0] is RadButtonElement)        
        {        
            e.CellElement.Children.Clear();     

within the CellFormatting routine?

Many thanks,
~Mike

0
Accepted
Nikolay
Telerik team
answered on 10 Jan 2009, 04:43 PM
Hello Mike,

I am now ready to provide you with the full resolution of your issue.

Let's first start with brief answers to the questions at the bottom of your latest reply:
1. It is possible to resolve the redraw issue. Actually, this is not an issue, but this is how RadGridView is expected to behave regarding the code snippet given. As pointed out in this Knowledge Base article, you should always reset the modified properties when a condition is not met. In short, you should always have and else clause for every if clause.
2. You will not need the custom cell approach, since my solution resolves the performance issue.

Now let me explain the answers in details:
1. As I mentioned above, you should always reset the modified properties when a condition is not met. Your code snippet was something like:
void radGridView1_CellFormatting(object sender, CellFormattingEventArgs e)     
{     
    if (e.CellElement is GridCommandCellElement)     
    {     
        if (e.CellElement.Children[0] is RadButtonElement)     
        {     
            e.CellElement.Children.Clear();     
    
            RadMenuElement buttonElement = new RadMenuElement();     
            buttonElement.Items.Add(new RadMenuItem("view"));     
            buttonElement.Items.Add(new RadMenuItem("modify"));     
            buttonElement.Items.Add(new RadMenuItem("release"));     
            buttonElement.Items.Add(new RadMenuItem("new"));     
            e.CellElement.Children.Add(buttonElement);    
 
            // Additional logic for showing and hiding the items  
        }     
    }      
}    
 

This code block inside the second 'if' statement will be executed only when RadGridView is initially displayed. The buttons will be removed, and the RadMenuElements will replace them. The additional logic will also be executed. Now, when you start scrolling, no logic is executed for the subelements, so you get redraw issues. You should have an 'else' statement, i.e. what should happen if the cell's child is RadMenuElement, but not RadButtonElement.

If you, however, remove the second 'if' statement, you will get instances of RadMenuElement and RadLabelElement created whenever a cell from the GridViewCommandColumn is being formatted. When you start scrolling, this creation process takes up some time and therefore you will get the performance penalty.

The resolution here is to create these instances only once for a visible cell and to manage these instances only by using their Visibility property:
if (e.CellElement is GridCommandCellElement)     
{     
    if (e.CellElement.Children[0] is RadButtonElement)     
    {     
        // create instances     
        // set additional logic to show/hide the elements     
    }     
    else    
    {     
        // set additional logic to show/hide the elements     
    }     
}     
 

So, the combination of creating the instances only once per cell and resetting the modified properties when a condition is not met is the key in your scenario. I am attaching a sample project where this approach is demonstrated.  I hope that this will help you.

If you have additional questions, feel free to contact me.

All the best,
Nikolay
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Mike
Top achievements
Rank 2
answered on 12 Jan 2009, 03:44 PM
Nikolay,

Thank you for the solution and pointing out the KB article - you have been a great help.  I will keep this in mind for future implimentations of the RadGrid.

Best regards,
~Mike
0
Nikolay
Telerik team
answered on 15 Jan 2009, 02:04 PM
Hi Mike,

I am glad to hear that I was of help. If you need further assistance, feel free to contact me.

Kind regards,
Nikolay
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
Tags
GridView
Asked by
Mike
Top achievements
Rank 2
Answers by
Mike
Top achievements
Rank 2
Nikolay
Telerik team
Share this question
or