+1-888-365-2779
Try Now
More in this section

Forums / General Discussions / External Pages

External Pages

12 posts, 0 answered
  1. Simon
    Simon avatar
    28 posts
    Registered:
    27 Jun 2008
    18 Aug 2008
    Link to this post
    I am trying to write a new UserControl that shows the children of the current section. The Site TreeView control comes close to what I am looking for but uses way too much markup for what I need, which is a nested <ul>

    So I am using nested Repeaters to output my nested lists, but am having problems making the External pages open and also with showing only 1 section at a time.

    This is what I currently have, I know I should refactor this into 2 methods, but that will come later...
    1<%@ Control Language="C#" AutoEventWireup="true" CodeFile="SubMenu.ascx.cs" Inherits="UserControls_SubMenu" %> 
    2<asp:SiteMapDataSource ID="SitemapDataSource1" runat="server" ShowStartingNode="false" /> 
    3<ul id="side_menu"
    4    <asp:Repeater ID="rpSubMenu" runat="server" DataSourceID="SitemapDataSource1"
    5        <ItemTemplate> 
    6            <li><asp:HyperLink runat="server" NavigateUrl='<%#Eval("Url") %>' Text='<%#Eval("Title") %>' /> 
    7                <asp:Repeater ID="rptSubMenu" runat="server"  
    8                    DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'  
    9                    OnItemDataBound="rptSubMenu_ItemDataBound"
    10                    <HeaderTemplate><ul></HeaderTemplate> 
    11                    <ItemTemplate> 
    12                        <li><asp:HyperLink ID="lnkSubLink" runat="server" NavigateUrl='<%#Eval("Url") %>' Text='<%#Eval("Title") %>' /></li
    13                    </ItemTemplate> 
    14                    <FooterTemplate></ul></FooterTemplate> 
    15                </asp:Repeater></li></ItemTemplate> 
    16    </asp:Repeater> 
    17</ul> 

    and in the code behind:
    1using System; 
    2using System.ComponentModel; 
    3using System.Xml; 
    4using System.Web.UI.WebControls; 
    5using System.Web.UI; 
    6using System.Web; 
    7using System.Collections; 
    8using Telerik.Cms; 
    9using Telerik.Cms.Web; 
    10 
    11 
    12public partial class UserControls_SubMenu : System.Web.UI.UserControl 
    13
    14    protected void Page_Load(object sender, EventArgs e) 
    15    { 
    16    } 
    17 
    18    [Browsable(true)] 
    19    [Category("Navigation")] 
    20    public bool ShowStartingNode 
    21    { 
    22        get 
    23        { 
    24            return this.SitemapDataSource1.ShowStartingNode; 
    25        } 
    26        set 
    27        { 
    28            this.SitemapDataSource1.ShowStartingNode = value; 
    29        } 
    30    } 
    31 
    32    [Browsable(true)] 
    33    [Category("Navigation")] 
    34    public int StartingNodeOffset 
    35    { 
    36        get { return this.SitemapDataSource1.StartingNodeOffset; } 
    37        set { this.SitemapDataSource1.StartingNodeOffset = value; } 
    38    } 
    39 
    40    protected void rptSubMenu_ItemDataBound(object sender, RepeaterItemEventArgs e) 
    41    { 
    42        CmsSiteMapNode node = e.Item.DataItem as CmsSiteMapNode; 
    43        if (node.CmsPage.PageType == CmsPageType.External) 
    44        { 
    45            HyperLink lnk = e.Item.DataItem as HyperLink; 
    46            lnk.Target = "_blank"
    47            //e.Item.Target = "_blank"; - there is no "Target" property 
    48        } 
    49 
    50        Repeater rpt = (Repeater)sender; 
    51        for (int i = 0; i < SiteMap.RootNode.ChildNodes.Count; i++) 
    52        { 
    53            if (SiteMap.CurrentNode.HasChildNodes || 
    54                (SiteMap.CurrentNode.ParentNode.HasChildNodes && 
    55                SiteMap.CurrentNode.ParentNode != SiteMap.RootNode.ChildNodes[i])) 
    56            { 
    57                rpt.Visible = true
    58            } 
    59            else 
    60            { 
    61                rpt.Visible = false
    62            } 
    63        } 
    64    } 
    65
    66 

    Currently I'm getting an "Object reference not set to an instance of an object" error on line 43 of my code behind and also all my nodes that have childnodes are open if i am in a section that has childnodes.
  2. Ivan
    Ivan avatar
    478 posts
    Registered:
    16 Jun 2015
    20 Aug 2008
    Link to this post
    Hello Simon,

    The problem is in the Repeater_ItemDataBound event handler. Namely, in the way that HyperLink control is being found. First of all, the HyperLink control should have an ID like in this sample where I've set it to "lnkMainLink":
    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="SubMenu.ascx.cs" Inherits="UserControls_SubMenu" %>    
    <asp:SiteMapDataSource ID="SitemapDataSource1" runat="server" ShowStartingNode="false" />    
    <ul id="side_menu">    
      <asp:Repeater ID="rpSubMenu" runat="server" DataSourceID="SitemapDataSource1">    
          <ItemTemplate>    
              <li><asp:HyperLink id="lnkMainLink" runat="server" NavigateUrl='<%#Eval("Url") %>' Text='<%#Eval("Title") %>' />    
                  <asp:Repeater ID="rptSubMenu" runat="server"     
                      DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'     
                      OnItemDataBound="rptSubMenu_ItemDataBound">    
                       <HeaderTemplate><ul></HeaderTemplate>    
                       <ItemTemplate>    
                           <li><asp:HyperLink ID="lnkSubLink" runat="server" NavigateUrl='<%#Eval("Url") %>' Text='<%#Eval("Title") %>' /></li>    
                       </ItemTemplate>    
                       <FooterTemplate></ul></FooterTemplate>    
                   </asp:Repeater></li></ItemTemplate>    
       </asp:Repeater>    
    </ul>   

    Then, you should modify the Repeater_ItemDataBound event handler in the following way:
    protected void rptSubMenu_ItemDataBound(object sender, RepeaterItemEventArgs e)    
    {    
        CmsSiteMapNode node = e.Item.DataItem as CmsSiteMapNode;    
        if (node.CmsPage.PageType == CmsPageType.External)    
        {    
        // find the hyper link control  
        HyperLink lnk = e.Item.FindControl("lnkMainLink");  
        // set the navigate url property of the hyper link  
            lnk.NavigateUrl = ((SiteMapNode)e.Item.DataItem).Url;    
        // set the target  
            lnk.Target = "_blank";    
        }    
         
        Repeater rpt = (Repeater)sender;    
        for (int i = 0; i < SiteMap.RootNode.ChildNodes.Count; i++)    
        {    
             if (SiteMap.CurrentNode.HasChildNodes ||    
                (SiteMap.CurrentNode.ParentNode.HasChildNodes &&    
                 SiteMap.CurrentNode.ParentNode != SiteMap.RootNode.ChildNodes[i]))    
             {    
                 rpt.Visible = true;    
             }    
             else    
             {    
                 rpt.Visible = false;    
             }    
        }    
    }  

    I hope you'll find this information helpful. Let us know if there is anything else we can do for you.

    Regards,
    Ivan
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  3. Simon
    Simon avatar
    28 posts
    Registered:
    27 Jun 2008
    20 Aug 2008
    Link to this post
    Hi Ivan,

    Thanks for your reply. I have modified my code, but am still getting an "Object reference not set to an instance of an object" error on
    if (node.CmsPage.PageType == CmsPageType.External) 

    Reading some other posts I have modified my code to add the rel attribute rather than target, but I don't think this is causing my problem.
    Here is my method:
    1protected void rptSubMenu_ItemDataBound(object sender, RepeaterItemEventArgs e) 
    2
    3    CmsSiteMapNode node = e.Item.DataItem as CmsSiteMapNode; 
    4 
    5    // Set External pages to open in new windows with rel="external" attribute 
    6    if (node.CmsPage.PageType == CmsPageType.External) 
    7    { 
    8        HyperLink lnk = (HyperLink)e.Item.FindControl("lnkMainLink"); 
    9        lnk.NavigateUrl = ((SiteMapNode)e.Item.DataItem).Url; 
    10        lnk.Attributes.Add("rel""external"); 
    11    } 
    12 
    13    // Show only the currently selected Nodes children  
    14    // or siblings if current node is a child of a main node. 
    15    // currently this shows all children for all nodes not just the current node. 
    16    Repeater rpt = (Repeater)sender; 
    17    for (int i = 0; i < SiteMap.RootNode.ChildNodes.Count; i++) 
    18    { 
    19        if (SiteMap.CurrentNode.HasChildNodes || 
    20           (SiteMap.CurrentNode.ParentNode.HasChildNodes && 
    21            SiteMap.CurrentNode.ParentNode != SiteMap.RootNode.ChildNodes[i])) 
    22        { 
    23            rpt.Visible = true
    24        } 
    25        else 
    26        { 
    27            rpt.Visible = false
    28        } 
    29    } 
    30

  4. Simon
    Simon avatar
    28 posts
    Registered:
    27 Jun 2008
    20 Aug 2008
    Link to this post
    Whooops and here's my control:
    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="SubMenu.ascx.cs" Inherits="UserControls_SubMenu" %> 
    <asp:SiteMapDataSource ID="SitemapDataSource1" runat="server" ShowStartingNode="false" /> 
    <ul id="side_menu"
        <asp:Repeater ID="rpSubMenu" runat="server" DataSourceID="SitemapDataSource1"
            <ItemTemplate> 
                <li><asp:HyperLink ID="lnkMainLink" runat="server" NavigateUrl='<%#Eval("Url") %>'  
                        Text='<%#Eval("Title") %>' /> 
                    <asp:Repeater ID="rptSubMenu" runat="server"  
                        DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'  
                        OnItemDataBound="rptSubMenu_ItemDataBound"
                        <HeaderTemplate><ul></HeaderTemplate> 
                        <ItemTemplate> 
                            <li><asp:HyperLink ID="lnkSubLink" runat="server" NavigateUrl='<%#Eval("Url") %>'  
                                    Text='<%#Eval("Title") %>' /></li
                        </ItemTemplate> 
                        <FooterTemplate></ul></FooterTemplate> 
                    </asp:Repeater></li></ItemTemplate> 
        </asp:Repeater> 
    </ul> 
     

  5. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    26 Aug 2008
    Link to this post
    Hello Simon,

    We managed to fix your control. Here is how it should look.

    Code behind:

    What we did:

    1. There is no data for header and footer items and we make sure that we are dealing with an Item or AlternatingItem

    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) 



    2.We checked if the CurrentNode is not null. There is no Current node and it cannot be returned in Admin section.

    if (SiteMap.CurrentNode != null) 



    public partial class mycontrols_SubMenu : System.Web.UI.UserControl 
        protected void rptSubMenu_ItemDataBound(object sender, RepeaterItemEventArgs e)  
            { 
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) 
            { 
                CmsSiteMapNode node = e.Item.DataItem as CmsSiteMapNode; 
     
                // Set External pages to open in new windows with rel="external" attribute  
                if (node.CmsPage.PageType == CmsPageType.External) 
                { 
                    HyperLink lnk = (HyperLink)e.Item.FindControl("lnkMainLink"); 
                    lnk.NavigateUrl = ((SiteMapNode)e.Item.DataItem).Url; 
                    lnk.Attributes.Add("rel", "external"); 
                } 
     
                // Show only the currently selected Nodes children   
                // or siblings if current node is a child of a main node.  
                // currently this shows all children for all nodes not just the current node.  
                Repeater rpt = (Repeater)sender; 
                for (int i = 0; i < SiteMap.RootNode.ChildNodes.Count; i++) 
                { 
                    if (SiteMap.CurrentNode != null) 
                    { 
                        if (SiteMap.CurrentNode.HasChildNodes || 
                           (SiteMap.CurrentNode.ParentNode.HasChildNodes && 
                            SiteMap.CurrentNode.ParentNode != SiteMap.RootNode.ChildNodes[i])) 
                            rpt.Visible = true
                        else 
                            rpt.Visible = false
                    } 
                } 
            } 
        } 






    And here is your .ascx. No changes have been made.

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="SubMenu.ascx.cs" Inherits="mycontrols_SubMenu" %>  
    <asp:SiteMapDataSource ID="SitemapDataSource1" runat="server" ShowStartingNode="false" />  
    <ul id="side_menu">  
        <asp:Repeater ID="rpSubMenu" runat="server" DataSourceID="SitemapDataSource1">  
            <ItemTemplate>  
                <li><asp:HyperLink ID="lnkMainLink" runat="server" NavigateUrl='<%#Eval("Url") %>'   
                        Text='<%#Eval("Title") %>' />  
                    <asp:Repeater ID="rptSubMenu" runat="server"   
                        DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'   
                        OnItemDataBound="rptSubMenu_ItemDataBound">  
                        <HeaderTemplate><ul></HeaderTemplate>  
                        <ItemTemplate>  
                            <li><asp:HyperLink ID="lnkSubLink" runat="server" NavigateUrl='<%#Eval("Url") %>'   
                                    Text='<%#Eval("Title") %>' /></li>  
                        </ItemTemplate>  
                        <FooterTemplate></ul></FooterTemplate>  
                    </asp:Repeater></li></ItemTemplate>  
        </asp:Repeater>  
    </ul>  


    Thank you for using our services.

    Regards,
    Ivan Dimitrov
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  6. Simon
    Simon avatar
    28 posts
    Registered:
    27 Jun 2008
    28 Aug 2008
    Link to this post
    Hi Ivan,

    Thanks for looking at this.
    I have copied the code you provided, but I am still getting the "Object reference not set to an instance of an object" error on the following line:
    lnk.NavigateUrl = ((SiteMapNode)e.Item.DataItem).Url; 


  7. Georgi
    Georgi avatar
    3583 posts
    Registered:
    28 Oct 2016
    01 Sep 2008
    Link to this post
    Hello Simon,

    The error you are getting suggests that one of the objects on that line is null. It is impossible to determine which one with certainty based only on that information, but here is my guess:

    In the ItemTemplate of your repeater there has to be a HyperLink control with id="lnkMainLink" (as per sample my colleague provided you with) and that HyperLink control must have runat="server" attribute. My guess is that the control is not there or its id is different.

    If this does not resolve the problem, please paste us the control and its code-behind and we will diagnose the problem for you.

    I hope you'll find this information helpful. Let us know if there is anything else we can do for you.

    Regards,
    Ivan
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  8. Simon
    Simon avatar
    28 posts
    Registered:
    27 Jun 2008
    01 Sep 2008
    Link to this post
    Hi Ivan,

    I already had the ID on my hyperlink, following previous advice. So here's the page markup:
    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="SubMenu.ascx.cs" Inherits="UserControls_SubMenu" %> 
    <asp:SiteMapDataSource ID="SitemapDataSource1" runat="server" ShowStartingNode="false" /> 
    <ul id="side_menu"
        <asp:Repeater ID="rpSubMenu" runat="server" DataSourceID="SitemapDataSource1"
            <ItemTemplate> 
                <li><asp:HyperLink ID="lnkMainLink" runat="server" NavigateUrl='<%#Eval("Url") %>'  
                        Text='<%#Eval("Title") %>' /> 
                    <asp:Repeater ID="rptSubMenu" runat="server"  
                        DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'  
                        OnItemDataBound="rptSubMenu_ItemDataBound"
                        <HeaderTemplate><ul></HeaderTemplate> 
                        <ItemTemplate> 
                            <li><asp:HyperLink ID="lnkSubLink" runat="server" NavigateUrl='<%#Eval("Url") %>'  
                                    Text='<%#Eval("Title") %>' /></li
                        </ItemTemplate> 
                        <FooterTemplate></ul></FooterTemplate> 
                    </asp:Repeater></li></ItemTemplate> 
        </asp:Repeater> 
    </ul> 
     


    and here's the code behind:

    using System; 
    using System.ComponentModel; 
    using System.Xml; 
    using System.Web.UI.WebControls; 
    using System.Web.UI; 
    using System.Web; 
    using System.Collections; 
    using Telerik.Cms; 
    using Telerik.Cms.Web; 
     
     
    public partial class UserControls_SubMenu : System.Web.UI.UserControl 
        protected void Page_Load(object sender, EventArgs e) 
        { 
        } 
     
        /// <summary> 
        /// (Exposed from contained SitemapDataSource.) Gets or sets a value indicating 
        /// whether the starting node is retrieved and displayed. 
        /// </summary> 
        /// <value> 
        ///     <strong>true</strong> if the starting node is displayed; otherwise, <b>false</b>. 
        /// The default is <b>false</b>. 
        /// </value> 
        /// <remarks> 
        /// The <b>ShowStartingNode</b> property is evaluated during calls to the GetView and 
        /// GetHierarchicalView methods, when the node tree that is returned by these methods is 
        /// populated. 
        /// </remarks> 
        [Browsable(true)] 
        [Category("Navigation")] 
        public bool ShowStartingNode 
        { 
            get { return this.SitemapDataSource1.ShowStartingNode; } 
            set { this.SitemapDataSource1.ShowStartingNode = value; } 
        } 
     
        [Browsable(true)] 
        [Category("Navigation")] 
        public int StartingNodeOffset 
        { 
            get { return this.SitemapDataSource1.StartingNodeOffset; } 
            set { this.SitemapDataSource1.StartingNodeOffset = value; } 
        } 
     
        protected void rptSubMenu_ItemDataBound(object sender, RepeaterItemEventArgs e) 
        { 
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) 
            { 
                CmsSiteMapNode node = e.Item.DataItem as CmsSiteMapNode; 
     
                // Set External pages to open in new windows with rel="external" attribute   
                if (node.CmsPage.PageType == CmsPageType.External) 
                { 
                    HyperLink lnk = (HyperLink)e.Item.FindControl("lnkMainLink"); 
                    lnk.NavigateUrl = ((SiteMapNode)e.Item.DataItem).Url; 
                    lnk.Attributes.Add("rel""external"); 
                } 
     
                // Show only the currently selected Nodes children    
                // or siblings if current node is a child of a main node.   
                // currently this shows all children for all nodes not just the current node.   
                Repeater rpt = (Repeater)sender; 
                for (int i = 0; i < SiteMap.RootNode.ChildNodes.Count; i++) 
                { 
                    if (SiteMap.CurrentNode != null
                    { 
                        if (SiteMap.CurrentNode.HasChildNodes || 
                           (SiteMap.CurrentNode.ParentNode.HasChildNodes && 
                            SiteMap.CurrentNode.ParentNode != SiteMap.RootNode.ChildNodes[i])) 
                            rpt.Visible = true
                        else 
                            rpt.Visible = false
                    } 
                } 
            } 
        }  
     




  9. Ivan
    Ivan avatar
    478 posts
    Registered:
    16 Jun 2015
    01 Sep 2008
    Link to this post
    Hi Simon,

    Here is your problem: you are handling the ItemDataBound event of the inner (nested) repeater, when you really want to do this on the outer repeater. To fix this, please move this line from rptSubMenu repeater to rpSubMenu (from inner to outer repeater):
    OnItemDataBound="rptSubMenu_ItemDataBound" 

    I hope you'll find this information helpful. Let us know if there is anything else we can do for you.

    Best wishes,
    Ivan
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  10. Simon
    Simon avatar
    28 posts
    Registered:
    27 Jun 2008
    01 Sep 2008
    Link to this post
    Hi Ivan,

    That's brilliant. That's fixed the object reference error.
    I am still getting all child nodes displayed for all parent nodes regardless of which section the user is currently on though.

    Is there a way to hide all children except for those of the current section?
  11. Ivan
    Ivan avatar
    478 posts
    Registered:
    16 Jun 2015
    01 Sep 2008
    Link to this post
    Hi Simon,

    I am glad we are making progress. I am not sure I have completely understood your question, but here is my best guess at what answer may be :)

    It seems to me that you want to bind the nested repeater only if the link in the outer repeater is the link of current page. In order to do so, you should modify your code as follows:

    protected void rptSubMenu_ItemDataBound(object sender, RepeaterItemEventArgs e)    
        {    
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)    
            {    
                CmsSiteMapNode node = e.Item.DataItem as CmsSiteMapNode;    
     
                // Set External pages to open in new windows with rel="external" attribute      
                if (node.CmsPage.PageType == CmsPageType.External)    
                {    
                    HyperLink lnk = (HyperLink)e.Item.FindControl("lnkMainLink");    
                    lnk.NavigateUrl = ((SiteMapNode)e.Item.DataItem).Url;    
                    lnk.Attributes.Add("rel""external");    
                }    
        
              // Show only the currently selected Nodes children       
              // or siblings if current node is a child of a main node.      
              // currently this shows all children for all nodes not just the current node.      
       
               Repeater rpt = (Repeater)sender;  
               if(SiteMap.CurrentNode != null && (SiteMap.CurrentNode.IsDescendantOf(node) || SiteMap.CurrentNode.Url == node.Url))  
                    rpt.Visible = true;  
               else 
                    rpt.Visible = false;   
            }    
        }     
     

    I hope this will solve your problem. Let us know if there is anything else we can do for you.

    Sincerely yours,
    Ivan
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  12. Simon
    Simon avatar
    28 posts
    Registered:
    27 Jun 2008
    02 Sep 2008
    Link to this post
    Hi Ivan,

    Yes that's just what I wanted to do. I only needed to modify 1 line to make this work
    Instead of
    Repeater rpt = (Repeater)sender;  


    It should be
    Repeater rpt = (Repeater)e.Item.FindControl("rptSubMenu"); 

    My control works now.
    Many thanks
Register for webinar
12 posts, 0 answered