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

Radtooltip RenderControl Method

5 Answers 71 Views
ToolTip
This is a migrated thread and some comments may be shown as answers.
Mathew
Top achievements
Rank 1
Mathew asked on 17 Jan 2012, 10:29 AM
Hi,

I have an asp.net application which uses the web part framework to allow users to customise their interface.  One of the features of this is a catalog of available web parts, one is provided by default, but it can be overriden if you wish to change the layout, etc.

override void RenderCatalogPart(HtmlTextWriter writer, CatalogPart catalogPart)

That, as far as I can tell, is the only way to do it.  At the moment I'm creating a panel with all the necessary elements in it, and using the panel's RenderControl method to output it to the htmlwriter.  So far, so good.  The problem occurs when I try to add a radtooltip to my panel, using the same RenderControl method, and I get the following runtime error:

Page cannot be null. Please ensure that this operation is being performed in the context of an ASP.NET request.

I can see why this might be a problem, since the tooltip presumably uses javascript and has to write it to the page - but the RenderCatalogPart method has no knowledge of which page it's going to be outputting to.  Is there any way around this or am I going to have to come up with an alternative?

Thanks,
Mathew

5 Answers, 1 is accepted

Sort by
0
Svetlina Anati
Telerik team
answered on 18 Jan 2012, 02:02 PM
Hi Mathew,

I built up a test demo based on your explanations and I was able to reproduce the problem. The problem comes from the fact that you register the RadToolTip too late and as being a script control this should be done in PreRender in spite of render.

This being said, to achieve what you need, please  follow the following steps:

1) Make sure you have added a ScriptManager on the page
2) Override PerformPreRender() method of your custom CatalogPartChrome
3) In the overridden in 2) method, add the tooltip to the Zone's Controls collection as follows:

public override void PerformPreRender()
{
    tip = new RadToolTip();
    tip.Text = "Test";
    tip.RelativeTo = ToolTipRelativeDisplay.BrowserWindow;
    tip.Position = ToolTipPosition.Center;
    tip.Width = 200;
    tip.Height = 200;
    tip.ManualClose = true;
    tip.VisibleOnPageLoad = true;
    this.Zone.Controls.Add(tip);
 
}

where tip is a global variable which will hold the reference to the tooltip.

4) Render the already registered tooltip in RenderCatalogPart method as you have already done:

public override void RenderCatalogPart(HtmlTextWriter writer, CatalogPart catalogPart)
        {
            base.RenderCatalogPart(writer, catalogPart);
            tip.RenderControl(writer);
        }

After I applied the above changes, everything started working correctly - for your convenience and reference I attached my sample demo to the thread.

I hope that my reply and the prepared demo are detailed enough and helpful, let me know how it goes.

 Greetings,

Svetlina Anati
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now
0
Mathew
Top achievements
Rank 1
answered on 18 Jan 2012, 03:24 PM
Hi Svetlina,

Thanks very much for your detailed reply, I've tested it and it works great.

Now all I need to do is figure out how I'm going to add one for each catalog part :)

Regards,
Mathew
0
Svetlina Anati
Telerik team
answered on 18 Jan 2012, 03:37 PM
Hi Mathew,

 
I am glad to hear I could help.

As to your new question, I suggest to use a collection, e.g you can use an ArrayList as follows:

public class MyCatalogPartChrome : CatalogPartChrome
    {
        ArrayList tips = new ArrayList();
 
        public MyCatalogPartChrome(CatalogZoneBase zone)
            : base(zone)
        {
 
        }
 
        public override void PerformPreRender()
        {
            foreach (CatalogPart p in Zone.CatalogParts)
            {
                RadToolTip tip = new RadToolTip();
                tip.Text = "Test";
                tip.RelativeTo = ToolTipRelativeDisplay.BrowserWindow;
                tip.Position = ToolTipPosition.Center;
                tip.Width = 200;
                tip.Height = 200;
                tip.ManualClose = true;
                tip.VisibleOnPageLoad = true;
                tips.Add(tip);
                p.Controls.Add(tip);
            }
 
        }
 
        public override void RenderCatalogPart(HtmlTextWriter writer, CatalogPart catalogPart)
        {
            base.RenderCatalogPart(writer, catalogPart);
            foreach (var tip in tips)
            {
                (tip as Control).RenderControl(writer);
            }
        }
    }
 
    public class MyCatalogZone : CatalogZone
    {
        protected override CatalogPartChrome CreateCatalogPartChrome()
        {
            return new MyCatalogPartChrome(this);
        }
    }


I tested this and it worked fine on my side.

Please, note, that you can verify that there are 3 tooltips in this case by looking at the $create directives when you view the source of the loaded page. Only one tooltip will be visible, though, because by design you can have only one visible tooltip at a given time - that is why you will have 3 tooltips added on the page, but the last added one will force the previous to close.

At last, this suggestion is the easiest and first one that came to my mind and I suggest it as a start point - you could think of another structure or apply some additional performance optimizations to fine-tune the solution.



All the best,
Svetlina Anati
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now
0
Mathew
Top achievements
Rank 1
answered on 20 Jan 2012, 04:41 PM
Hi Svetlina,

I've done as you suggested and used the collection - I'm almost there, I can get the tooltips to render, but not to attach them to the specific controls.

public override void PerformPreRender()
{
    base.PerformPreRender();
    toolTips = new List<RadToolTip>();
    panels = new List<Panel>();
 
    foreach (CatalogPart cp in Zone.CatalogParts)
    {
        foreach (WebPartDescription partDescription in cp.GetAvailableWebPartDescriptions())
        {
            PortalWebPartBase webPart = cp.GetWebPart(partDescription) as PortalWebPartBase;
            RadToolTip t = new RadToolTip()
            {
                HideEvent = ToolTipHideEvent.ManualClose,
                ShowEvent = ToolTipShowEvent.OnMouseOver,
                RelativeTo = ToolTipRelativeDisplay.Element
                RegisterWithScriptManager = true
            };
            Panel panel = CreatePanelForWebPart(partDescription, webPart);
            panel.ID = String.Format(CultureInfo.InvariantCulture, "DescriptionPanel{0}", partDescription.ID);
            panels.Add(panel);
                 
            t.TargetControlID = panel.UniqueID;
            t.IsClientID = true;
            t.ID = String.Format(CultureInfo.InvariantCulture, "DescriptionPanelTip{0}", partDescription.ID);
            toolTips.Add(t);
            this.Zone.Controls.Add(t);
            this.Zone.Controls.Add(panel);
       }
    }
}

I'm then rendering both panels and tooltips in the RenderCatalogPart method, and the tooltips simply don't show up.  If I set one to be visible when the page loads, I get a window is undefined error.  I've also tried using javascript to call the tooltip's .show() method clientside when the mouse enters the panel, but I get a nullref when using <% find .... and when using document.getElementById().

Any suggestions?
0
Mathew
Top achievements
Rank 1
answered on 20 Jan 2012, 04:44 PM
Actually, never mind, I've been able to get it to work now!  It's broken something else with the web part catalog, but I'm sure I'll be able to fix that.
Tags
ToolTip
Asked by
Mathew
Top achievements
Rank 1
Answers by
Svetlina Anati
Telerik team
Mathew
Top achievements
Rank 1
Share this question
or