Page Group Bug
Hi There,
string title = new PageManager().GetPageNode(new Guid(SiteMapBase.GetCurrentProvider().CurrentNode.Key)).Title;
Hi There,
Hi Phill ,
You can identify the whether a page is Group or not by checking the PageNode.Page. The Group page does not have PageData.
var node = pageManager.GetPageNode(id);
var isGroupPage = node.Page ==
null
;
if
(!isGroupPage)
Hi,
Hi Webinsite,
How have you generated the SiteMap? Generally you should have a xml datasource with all page nodes. If you exclude the page groups or the first page you will not get duplicate content. This will increase the weight of the url.
We will have an internal discussion about how to change the behavior of page group and the first page. Our initial idea is to expose some option for permanent redirect from the group page to the first child and vice versa, so crawlers will not be affected. Any other ideas are appreciated.
Greetings,
Ivan Dimitrov
the Telerik team
Hi Ivan,
SiteMapNode cNode = e.Item.DataItem as SiteMapNode;
PageSiteNode node = (PageSiteNode)cNode;
if (node.IsGroupPage)
SiteMapNodeCollection nodeCollection = node.ChildNodes;
// Set the Url of the PageGroup item to the Url of the first page in group
if(nodeCollection[0] != null)
e.Item.NavigateUrl = nodeCollection[0].Url;
private void GetRootNode(SiteMapNode node)
if (node.ParentNode.ParentNode == null)
var item = RadMenu1.FindItemByUrl(Page.ResolveUrl(node.Url));
if(item != null)
item.ImageUrl = item.ExpandedImageUrl;
else
GetRootNode(node.ParentNode);
Hi Phill,
Using GetFirstPageDataNode and GetActualCurrentNode methods should fix the issue you have, because this returns the actual item and the actual url of it. Using a while loop you can highlight the path to the root. The group page does not have PageData additional check for this will return whether the parent is group or not, so you can highlight it by getting an instance to the current menu item which is in the loop - you have direct access to it from the arguments of ItemDataBound event
Greetings,
Ivan Dimitrov
the Telerik Dev team
Hi Ivan,
I'm wondering if you can help me with the issue I'm having. The problem is that in order to get the GroupPage to behave as it should, I'm changing it's url to the url of the first item. The call to GetFirstPageDataNode() makes this much easier and works great in the RC2. However, this means that my RadMenu now has two nodes with the same url so my code used in the loop to find the root:
var item = RadMenu1.FindItemByUrl(Page.ResolveUrl(node.Url));
Hi Ivan,
I just want to clarify - this bug occurs using the built in navigation control with no modifications - so I don't quite understand what you were asking about the generated sitemap.... I dropped in the SF navigation control into the page, no custom work.
As for how to remeady the situation - if this wasn't the behaviour in 3.x for the sitemenu control why don't you just do the same thing you did in 3.x? Seems to me to be the logical thing to do.
Cheers,
Seth
Hi,
Google Webmaster tools can use XML SiteMap which helps Google to find pages on your website and you can specify the web address of a single page. There is a SiteMap generator that google offers and I thought that you use this way.
Currently when you go to a group page we load the first page in the same window and SiteMap.CurrentNode returns the group page instead of the first page. This is why we have GetActualCurrentNode method.
We will have an internal discussion about how to change the behavior of page group and the first page. Our initial idea is to expose some option for permanent redirect from the group page to the first child and vice versa, so crawlers will not be affected. Any other ideas are appreciated.
All the best,
Ivan Dimitrov
the Telerik team
Has there been any movement on this? I've run up against this issue as well, not for Google indexing reasons, but because I have a sidebar navigation control that uses the value of a RadSiteMap control's SelectedNode property to change the CSS of the related item in the navigation control. This control won't pick up the selected page when someone clicks on the group page on a different site-wide navigation control.
I could fake this out by testing for the URL explicitly, but this control is reused in several areas that have similar group setups, so that wouldn't be a very robust solution.
Josh
I am curious - Phil - did you get it to work? You mentioned that you - created a menu from scratch and in the itemdatabound of the repeater changing the Url of group menu items to the url of the first item in the group. How much from scratch did you have to create? Can the exisiting -say navigation tree control be modified to do this?
Thank you
Laura
Hi Laura,
I based my menu on a User Control I had created for a SF 3.7 site. Part of the reason I created it from scratch was because my design required my top level items to be graphics so this complicated things further. In case it helps, here's what I came up with
MainMenu.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MainMenu.ascx.cs" Inherits="SitefinityWebApp.Custom.Navigation.MainMenu" %>
<
asp:SiteMapDataSource
ID
=
"SiteMapDataSource1"
runat
=
"server"
ShowStartingNode
=
"false"
/>
<
telerik:RadMenu
ID
=
"RadMenu1"
runat
=
"server"
DataSourceID
=
"SitemapDataSource1"
EnableEmbeddedBaseStylesheet
=
"true"
EnableEmbeddedSkins
=
"false"
EnableOverlay
=
"true"
EnableScreenBoundaryDetection
=
"false"
EnableRoundedCorners
=
"false"
EnableShadows
=
"false"
DefaultGroupSettings-Width
=
"150"
>
</
telerik:RadMenu
>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Telerik.Sitefinity.Web;
using Telerik.Sitefinity.Modules.Pages;
using Telerik.Sitefinity.Modules.Pages.Web.UI;
using Telerik.Web.UI;
using Telerik.Web.UI.Design;
namespace SitefinityWebApp.Custom.Navigation
[RequireScriptManager]
public partial class JDNAMenu : System.Web.UI.UserControl
string currentLang = "en";
protected void Page_Load(object sender, EventArgs e)
if (!this.IsDesignMode())
this.RadMenu1.ItemDataBound += new Telerik.Web.UI.RadMenuEventHandler(RadMenu1_ItemDataBound);
void RadMenu1_ItemDataBound(object sender, Telerik.Web.UI.RadMenuEventArgs e)
SiteMapNode cNode = e.Item.DataItem as SiteMapNode;
PageSiteNode node = (PageSiteNode)cNode;
// Hide the menu item if set to not show in navigation or if hidden
if (!node.ShowInNavigation || node.Hidden)
e.Item.Visible = false;
// Set group node url to url of first page to fix SF4 Page Group BUG!!!!
if (node.IsGroupPage)
SiteMapNode gNode = SiteMapBase.GetFirstPageDataNode(node);
e.Item.NavigateUrl = gNode.Url;
// Custom Code to support image buttons for the top level menu items
if (e.Item.Level == 0)
SiteMapNode dataItem = e.Item.DataItem as SiteMapNode;
if (dataItem != null)
e.Item.ImageUrl = "~/images/nav/main-" + dataItem.Title.Trim().Replace(" ", "") + "-" + currentLang + "-off.jpg";
e.Item.HoveredImageUrl = "~/images/nav/main-" + dataItem.Title.Trim().Replace(" ", "") + "-" + currentLang + "-on.jpg";
e.Item.Text = "";
// Set Current Top Level Node to Selected
SiteMapNode currentNode = SiteMapBase.GetCurrentProvider().CurrentNode;
if (currentNode != null)
var item = RadMenu1.FindItemByUrl(Page.ResolveUrl(currentNode.Url));
if (item != null)
SiteMapNode curItem = item.DataItem as SiteMapNode;
if (curItem != null)
if (item.Level == 0)
// Select top level item
item.ImageUrl = "~/images/nav/main-" + curItem.Title.Trim().Replace(" ", "") + "-" + currentLang + "-on.jpg";
else if (item.Level > 0)
// Select top menu item when a sub item is selected
GetRootNode(currentNode);
/// <
summary
>
/// Calls itself until it gets the section one level below the root
/// </
summary
>
/// <
param
name
=
"node"
></
param
>
private void GetRootNode(SiteMapNode node)
if (node.ParentNode.ParentNode == null)
var item = RadMenu1.FindItemByValue(node.Title);
if(item != null)
item.ImageUrl = item.HoveredImageUrl;
else
GetRootNode(node.ParentNode);
Thank you so much Phill. For the sub nav's on the left hand side, were you able to program the starting node offset there too? Or did you have to have a different template for each main section?
Hi Laura, the side menu is a RadPanelBar. In the current site structure the content doesn't get grouped after the first level so I didn't have to worry about the Page Group bug there but the same approach would most likely apply. In case you haven't used it before, the site menu was as follows:
SideMenu.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SideMenu.ascx.cs" Inherits="SitefinityWebApp.Custom.Navigation.SideMenu" %>
<
h4
><
asp:Literal
ID
=
"litSectionTitle"
runat
=
"server"
/></
h4
>
<
asp:SiteMapDataSource
ID
=
"SiteMapDataSource1"
runat
=
"server"
ShowStartingNode
=
"false"
StartingNodeOffset
=
"1"
/>
<
telerik:RadPanelBar
ID
=
"RadPanelbar1"
runat
=
"server"
DataSourceID
=
"SiteMapDataSource1"
OnItemDataBound
=
"RadPanelbar1_ItemDataBound"
EnableViewState
=
"false"
AllowCollapseAllItems
=
"false"
ExpandMode
=
"MultipleExpandedItems"
Width
=
"130"
EnableEmbeddedSkins
=
"false"
EnableEmbeddedBaseStylesheet
=
"true"
>
</
telerik:RadPanelBar
>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Telerik.Sitefinity.Web;
using Telerik.Sitefinity.Modules.Pages;
using Telerik.Sitefinity.Modules.Pages.Web.UI;
using Telerik.Web.UI;
namespace SitefinityWebApp.Custom.Navigation
[RequireScriptManager]
public partial class SideMenu : System.Web.UI.UserControl
protected void Page_Load(object sender, EventArgs e)
if (!Page.IsPostBack)
if (!this.IsDesignMode())
SiteMapNode cNode = SiteMapBase.GetCurrentProvider().CurrentNode;
if (cNode != null)
if (cNode.ParentNode.ParentNode == null)
litSectionTitle.Text = new PageManager().GetPageNode(new Guid(SiteMapBase.GetCurrentProvider().CurrentNode.Key)).Title;
else
GetSection(cNode);
/// <
summary
>
/// Calls itself until it gets the section one level below the root
/// </
summary
>
/// <
param
name
=
"node"
></
param
>
protected void GetSection(SiteMapNode node)
if (node.ParentNode.ParentNode == null)
litSectionTitle.Text = node.Title;
else
GetSection(node.ParentNode);
#region Properties
[Browsable(true)]
[Category("Navigation")]
public int StartingNodeOffset
get
return this.SiteMapDataSource1.StartingNodeOffset;
set
this.SiteMapDataSource1.StartingNodeOffset = value;
[Browsable(true)]
[Category("Navigation")]
public bool StartFromCurrentNode
get
return this.SiteMapDataSource1.StartFromCurrentNode;
set
this.SiteMapDataSource1.StartFromCurrentNode = value;
[Browsable(true)]
[Category("Navigation")]
[DefaultValue(false)]
public bool ShowStartingNode
get
return this.SiteMapDataSource1.ShowStartingNode;
set
this.SiteMapDataSource1.ShowStartingNode = value;
#endregion
#region Methods
public void RadPanelbar1_ItemDataBound(object sender, RadPanelBarEventArgs e)
SiteMapNode cNode = e.Item.DataItem as SiteMapNode;
PageSiteNode node = (PageSiteNode)cNode;
// Hide the menu item if set to not show in navigation or if hidden
if (!node.ShowInNavigation || node.Hidden)
e.Item.Visible = false;
#endregion
Thank you for sharing that Phill. I was pulling my hair out trying to figure out if I misunderstood how page groups should work. I had the same need for menu functionality and your example put me on the right path.
Firstly thanks Phill, now that i know to get my naviagtion to work as expected i need to create a custom control and use that.
secondly can we have page groups back to the way they used to be and not try and be clever with it. if it is a group just load the first page in that group with the correct url!
Rob
I have a problem with the page group as well.
Under the page group i have 4 child pages. They all have the Navigation control configured to show siblings (as a right side menu).
That works as expected when I view the individual pages. I get a navigation control with the four pages.
I have set the page group page to select the first child page. When I select the pagegroup in my top menu it shows the content from the first child page - but the navigation control still thinks that it is at the top level.
I have also tried to change the page type to redirect, but it won't let me select child pages. (There's also another bug - if I try to type the absolute url - it won't let me save the settings. No error is displayed)
Regards, Dennis
Hello,
The behavior of page groups is by design that it would show the content of the first child page. This behavior is such because we have had numerous request to be able to simulate default document as with ASP.NET website. For example if you put a default document for a folder in an ASP.NET webiste and navigate to the url of the folder you will not see default.aspx in the url (similar to home page behavior).
The problem is with our Navigation control and it is going to be fixed together with the Sitemap refactoring task we have planned for the 4.2 release.
Best wishes,
Radoslav Georgiev
the Telerik team
Phill,
I know its been a long time but I finally implemented the code you posted above for the horizontal navigation. and it works beautifully.
Thank you so very much!
Laura
We have recently upgraded to the latest 4.2 release because of a News error bug that wouldn't allow me to get back into the News section.
However, with the custom code on this page I now get this error.
Above you mentions something about now using Sitemap refactoring. Is there something different I should be doing?
Thank you.
Compiler Error Message: CS0117: 'Telerik.Sitefinity.Web.SiteMapBase' does not contain a definition for 'GetFirstPageDataNode'
Source Error:
Line 41: if (node.IsGroupPage)
Line 42:
Line 43: SiteMapNode gNode = SiteMapBase.GetFirstPageDataNode(node);
Line 44: e.Item.NavigateUrl = gNode.Url;
Line 45:
Hello Laura,
Please use GetActualCurrentNode() instead.
Greetings,
Ivan Dimitrov
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>
Finally revisiting this -
For the top level navigation, I am only getting the Home page (which is not a group page.)
It doesn't show the page group pages at all in the navigation... ?
And I am using "Please use GetActualCurrentNode()"
Any ideas? Thank you.
Hi Laura,
Can you post the code that you use for binding the navigation to your databound control?
Regards,
Ivan Dimitrov
the Telerik team
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MainMenu.ascx.cs" Inherits="Custom.Navigation.MainMenu" %>
<
asp:SiteMapDataSource
ID
=
"SiteMapDataSource1"
runat
=
"server"
ShowStartingNode
=
"false"
/>
<
telerik:RadMenu
ID
=
"RadMenu1"
runat
=
"server"
DataSourceID
=
"SitemapDataSource1"
EnableEmbeddedBaseStylesheet
=
"true"
EnableEmbeddedSkins
=
"false"
EnableOverlay
=
"true"
EnableScreenBoundaryDetection
=
"false"
EnableRoundedCorners
=
"false"
EnableShadows
=
"false"
DefaultGroupSettings-Width
=
"150"
CssClass
=
"main-nav"
>
</
telerik:RadMenu
>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Telerik.Sitefinity.Web;
using Telerik.Sitefinity.Modules.Pages;
using Telerik.Sitefinity.Modules.Pages.Web.UI;
using Telerik.Web.UI;
using Telerik.Web.UI.Design;
namespace Custom.Navigation
[RequireScriptManager]
public partial class MainMenu : System.Web.UI.UserControl
string currentLang = "en";
protected void Page_Load(object sender, EventArgs e)
if (!this.IsDesignMode())
this.RadMenu1.ItemDataBound += new Telerik.Web.UI.RadMenuEventHandler(RadMenu1_ItemDataBound);
void RadMenu1_ItemDataBound(object sender, Telerik.Web.UI.RadMenuEventArgs e)
SiteMapNode cNode = e.Item.DataItem as SiteMapNode;
PageSiteNode node = (PageSiteNode)cNode;
// Hide the menu item if set to not show in navigation or if hidden
if (!node.ShowInNavigation || node.Hidden)
e.Item.Visible = false;
// Set group node url to url of first page to fix SF4 Page Group BUG!!!!
// change GetFirstPageDataNode to GetActualCurrentNode() after 4.2 upgrade
if (node.IsGroupPage)
SiteMapNode gNode = SiteMapBase.GetActualCurrentNode();
e.Item.NavigateUrl = gNode.Url;
// Custom Code to support image buttons for the top level menu items
if (e.Item.Level == 0)
SiteMapNode dataItem = e.Item.DataItem as SiteMapNode;
if (dataItem != null)
//e.Item.ImageUrl = "~/images/nav/main-" + dataItem.Title.Trim().Replace(" ", "") + "-" + currentLang + "-off.jpg";
//e.Item.HoveredImageUrl = "~/images/nav/main-" + dataItem.Title.Trim().Replace(" ", "") + "-" + currentLang + "-on.jpg";
//e.Item.Text = "";
// Set Current Top Level Node to Selected
SiteMapNode currentNode = SiteMapBase.GetCurrentProvider().CurrentNode;
if (currentNode != null)
var item = RadMenu1.FindItemByUrl(Page.ResolveUrl(currentNode.Url));
if (item != null)
SiteMapNode curItem = item.DataItem as SiteMapNode;
if (curItem != null)
if (item.Level == 0)
// Select top level item
//item.ImageUrl = "~/images/nav/main-" + curItem.Title.Trim().Replace(" ", "") + "-" + currentLang + "-on.jpg";
else if (item.Level > 0)
// Select top menu item when a sub item is selected
GetRootNode(currentNode);
/// <
summary
>
/// Calls itself until it gets the section one level below the root
/// </
summary
>
/// <
param
name
=
"node"
></
param
>
private void GetRootNode(SiteMapNode node)
if (node.ParentNode.ParentNode == null)
var item = RadMenu1.FindItemByValue(node.Title);
if (item != null)
//item.ImageUrl = item.HoveredImageUrl;
else
GetRootNode(node.ParentNode);
Hi Laura,
Dont know if this will help, and i could have completely missed the point, as i thought GetActualCurrentNode was the current page you were on??, but coudnt you use:
node.Nodes[0].GetUrl();
SiteMapNode gNode = SiteMapBase.GetActualCurrentNode();
e.Item.NavigateUrl = gNode.Url;