Tuesday, May 27, 2014

Fixing Telerik's RadToolTip After Latest Releases Broke It


Ok, so I had the following scenario.  I was using a Telerik Radgrid with a gridtemplate column that displayed user comments.  Often the comments were long so I would truncate the comment text that would be displayed, and then I add a RadToolTip with the target of the comment label in the grid that on hover would display the full comment text in a tool tip.  But then something happened...the latest changes broke the tool tip so that if I did anything on the grid like sort, update a row, whatever often the comment tool tip would become blank.  I read that it has something to do with how the radtooltip now stores it's content in the viewstate...well that was the excuse, but IMHO it is broke as it worked before and it doesn't work now.

The Fix

Step 1) Add a RadToolTipManager to your page, outside of your update pannels.  Here is an example

   <telerik:RadToolTipManager ID="RadToolTipManager1" runat="server" OnAjaxUpdate="RadToolTipManager1_AjaxUpdate"  
    RelativeTo="Element" Position="TopLeft" Width="450" ManualClose="True" ShowDelay="600"  

Notice there is an OnAjaxUpdate method.  You will have to add that in your code behind, but let's worry about that in a second.

Step 2: Add a or update an existing RadGrid ItemDataBound event so we can add a tool tip on to each comment field.

 if ( e.Item.OwnerTableView.Name == "MasterTableName" && ( e.Item.ItemType == GridItemType.Item || e.Item.ItemType == GridItemType.AlternatingItem ) )  
     Control cntl = e.Item.FindControl ( "mylabelintemplatecontrolidwithtruncatedtext" );  
     if ( cntl != null )  
      if ( this.RadToolTipManager1 != null )  
       this.RadToolTipManager1.TargetControls.Add ( cntl.ClientID, true );  

Note: I'm doing the e.Item.OwnerTableView.Name check because I'm using a grid with detail tables. If you don't have any detail tables you can skip that part of the check.  You might also add in a check to make sure the Radgrid is in read only mode, I didn't but I might go back and do that just to make it more efficient.

Step 3) Add your RadToolTipManager Ajax update method.

   protected void RadToolTipManager1_AjaxUpdate ( object sender, Telerik.Web.UI.ToolTipUpdateEventArgs e )  
    for ( int i = 0 ; i < MyGridView.Items.Count ; i++ )  
     if ( MyGridView.Items[ i ].OwnerTableView.Name == "MasterTableName" && ( MyGridView.Items[ i ].ItemType == GridItemType.Item || MyGridView.Items[ i ].ItemType == GridItemType.AlternatingItem ) )  
      /* unfortunately only get client ID back on ajax method, so we have to loop to find matching client ID */  
      Control cntl = MyGridView.Items[ i ].FindControl ( "mylabelintemplatecontrolidwithtruncatedtext" );  
      if ( cntl != null && cntl.ClientID == e.TargetControlID )  
       /* get row ID number */  
       int myID = Convert.ToInt32(MyGridView.Items[ i ].GetDataKeyValue ( "myID" ));  
        /* now get full comment text out of the database */  
        var rv = ( from myrow in ( (DataView)MyDataSet.Select ( DataSourceSelectArguments.Empty ) ).ToTable ().AsEnumerable ()  
              where ( myrow.Field<int> ( "myID" ) == myID )  
              select myrow ).FirstOrDefault ();  
       Label lblInsideToolTip = new Label ();  
       lblInsideToolTip.Text = rv[ "mycommenttextfield" ].ToString ();  
       e.UpdatePanel.ContentTemplateContainer.Controls.Add ( lblInsideToolTip );  

Ok, a few comments on Step 3.  I could only get the ClientID of the target control from the Telerik.Web.UI.ToolTipUpdateEventArgs object, so I had to loop through all of my RadGrid items and then try match client ID's of the column I was looking for.  Kind of a bummer. I elected to grab the comment text from the Dataset itself.  There are other ways of doing this.  Also this is just demo code, you might want to add this in a big try catch or at least check for more nulls.


This seems to work.  I can sort, edit, insert rows and now the comment field's tool tip is always current.  I hope this code helps. Also be sure to add the using System.Linq at the top of the page in your code behind if it isn't there.

No comments: