Radtooltip RenderControl Method

6 posts, 0 answers
  1. Mathew
    Mathew avatar
    27 posts
    Member since:
    Jul 2011

    Posted 17 Jan 2012 Link to this post

    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
  2. Svetlina Anati
    Admin
    Svetlina Anati avatar
    2795 posts

    Posted 18 Jan 2012 Link to this post

    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
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Mathew
    Mathew avatar
    27 posts
    Member since:
    Jul 2011

    Posted 18 Jan 2012 Link to this post

    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
  5. Svetlina Anati
    Admin
    Svetlina Anati avatar
    2795 posts

    Posted 18 Jan 2012 Link to this post

    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
  6. Mathew
    Mathew avatar
    27 posts
    Member since:
    Jul 2011

    Posted 20 Jan 2012 Link to this post

    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?
  7. Mathew
    Mathew avatar
    27 posts
    Member since:
    Jul 2011

    Posted 20 Jan 2012 Link to this post

    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.
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017