PANVEGA’s Blog

DotNet Development, SharePoint Customizing, Silverlight, MS Infrastructure and other tips and tricks

Custom Silverlight Navigation with the SP PortalSiteMapProvider

Posted by PANVEGA on June 2, 2009

In this post I wanna explain in a few steps how to develope a custom Silverlight Navitgation for SharePoint publishing sites (Source Silverlight Blueprints on CodePlex)

SharePoint and Silverlight Blueprints on CodePlex were uploaded to include two more Silverlight RTM samples: custom navigation in SharePoint and the colleague viewer. These blueprints provide samples for you to build and explore using Silverlight as an alternate way to develop and integrate powerful user experiences within SharePoint and add rich Internet application functionality to your SharePoint sites. Included in the overall set of samples are a Hello World sample, a Slider sample, and the recently added Custom Navigation and Colleague Viewer samples added

Creating the Navigation Project

The navigation control is a class that inherits from the SPControl class and it creates the required infrastructure for becoming a Silverlight 2 application host container (that is, ensuring there is a ScriptManager available and the creation of a Silverlight control object).

  • Create a new Visual Studio 2008 C# project
  • Before you can start coding you need to add a reference to the System.Web.Silverlight.dll (version 2.0.5.0) and to the System.Web.Extensions.dll (version 3.5.0.0).
  • Override the OnLoad method in which you need to check whether a script manager already exists on the page. If not, you have to add one at the first position of the Controls collection

base.OnInit(e);

smgr = ScriptManager.GetCurrent(this.Page);
if (smgr == null)
{
smgr = new ScriptManager();
this.Controls.Add(smgr);
}

  • Inherite from SPControl (Provides methods for getting or setting the context of the request and serves as the base server control from which other controls in the Microsoft.SharePoint.WebControls namespace derive)
  • Initialize a SiteMapProvide like:

SiteMapProvider siteMapProvider = SiteMap.Providers[SiteMapProviderName];

portalSiteMapProvider = siteMapProvider as PortalSiteMapProvider;
portalSiteMapProvider.DynamicChildLimit = 0;
portalSiteMapProvider.EncodeOutput = true;
portalSiteMapProvider.IncludePages = PortalSiteMapProvider.IncludeOption.Always;
portalSiteMapProvider.IncludeSubSites = PortalSiteMapProvider.IncludeOption.Never;

  • Once a valid reference is retrieved, properties are set for the PortalSiteMapProvider to grab only pages and no sub sites.
  • Create a new XmlDocument, which parses through the PortalSiteMapProvider and adds the current SiteNodes (URL, Title, Description, Comments and Images))  to the XML
  • Note: If you want to get all Subsites instead of the PublishingWeb you have to use like:

Programmatically accessing current navigation in SharePoint Publishing with the ProtalSiteMapProvider

You can find the PortalSiteMapProvider in the namespace

using Microsoft.SharePoint.Publishing.Navigation;

PortalSiteMapProvider map = new PortalSiteMapProvider();

foreach (SiteMapNode pageNode in map.CurrentNode.ChildNodes)
{…….}

In general, you shouldn’t create new instances of PortalSiteMapProvider to be discarded after use in a single method. These objects contribute to a lot of memory use and are designed to be shared across a large number of requests. Any PortalSiteMapProvider instances declared in web.config can be accessed with:

PortalSiteMapProvider portalProvider = (PortalSiteMapProvider)SiteMap.Providers["<InstanceName>"];

This code below returns a sorted list without the navigation nodes which are hided. You can also access a certain node by using the method FindSiteMapNode with an Url as the parameter.

PortalSiteMapProvider map = new PortalSiteMapProvider();
SiteMapNode node = map.FindSiteMapNode(“/PressReleases”);
SiteMapNodeCollection nodeColl = node.ChildNodes;

  • You’ll encounter lines of code that communicate and loop over the nodes delivered by the PortalSiteMapProvider, combined with calls to the Microsoft.SharePoint.Publishing API for retrieving more info about the page in question
  • Create a new Silverlight Control
  • Within the CreateChildControls method that is already prepared for you, you have to instantiate the Silverlight control and set its properties. One of these properties is the Source property. The setting depends on where you are going to deploy your silverlight application. In this sample I will deploy the Silverlight application as an embedded resource of my SharePoint Web Part so the Source property has to point to that location. I will come back to this property once the Silverlight application is created. Don’t forget to specify a Width and Height, otherwise the Silverlight application will not be visible.
  • Another property that is worth mentioning is the InitParameters property. I use this property to pass the URL to the SharePoint site and the name from the list that needs to be queried. The retrieval of the data, and thus the communication with SharePoint, will be done from within the Silverlight application. Notice that this property is a string. You can pass data in it by respecting the syntax name1=value1,name2=value2,… Within the Silverlight application this data will be unpacked in a dictionary. But more on this in next section.Don’t forget to add the Silverlight control to the Controls collection of the Web Part.

silverlightControl.ID = “SL2Navigation”;
silverlightControl.Source = SPContext.Current.Site.Url + “/_Layouts/BluePrintMP/SL.XAML.NavigationControl.xap”;
silverlightControl.Width = new System.Web.UI.WebControls.Unit(165);
silverlightControl.Height = new System.Web.UI.WebControls.Unit(420);
silverlightControl.InitParameters = “ctlid=SL_NAVDATA”;

  • Finnaly you have to add the new created XmlDocument to your Application Controls

string xmlDataIsland = “<XML id=’SL_NAVDATA’>{0}</XML>”;
literalXMLIsland = new LiteralControl(string.Format(xmlDataIsland, xmlDoc.DocumentElement.OuterXml));
this.Controls.Add(literalXMLIsland);

  • Notice the creation of a LiteralControl instance that will contain the XML Data Island and the passing of the ID of this XML Data Island as value of the InitParameters property of the Silverlight control.

Create a new MasterPage

If you install the sample and activate the Feature, a new master page will become available in the Master Pages and Page Layouts Gallery for your site collection. The master page is a copy of the blueband.master. You’ll find a Register directive at the top of the master page:

<%@ Register TagPrefix=”SL” Namespace=”SL.Controls.Navigation” Assembly=”SL.Controls.Navigation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4aec304184eb9a69″ %>

And further down, there is the inclusion of the navigation control with the setting of the name of the PortalSiteMapProvider to connect to.

<asp:ContentPlaceHolder id=”PlaceHolderLeftNavBar” runat=”server”>
<br>
<!– Current Navigation –>
<SL:SilverlightSPMenu runat=”server” SiteMapProviderName=”CurrentNavSiteMapProvider”></SL:SilverlightSPMenu>
</asp:ContentPlaceHolder>

Your SL MenuListBox will replace in the PlaceHolderLeftNavBar the QuickLaunch NavBar

Creating a Silverlight Application

The development of the Silverlight application is a bit harder, certainly if you are a normal ASP.NET or SharePoint developer. Add a new project to the solution using the Silverlight Application template. This template comes with a standard Page.xaml and an App.xaml. The App.xaml file inherits from the System.Windows.Application class which represents the Silverlight application while the Page represents a Silverlight control.

Before designing the Silverlight controls you will have to retrieve the parameters that have been passed by the Navigation Control, which was added the Controls class. Open the App.xaml.cs file and locate the Application_Startup method. The second incoming argument is of type StartUpEventArgs and contains in its InitParams property the data you passed in via the Web Part. At this side of the Silverlight application it is a dictionary of key-value pairs.

App.xaml.cs

  • To be able to use this data from within the Silverlight application you have to pass the data to constructor of the Page control.

if (e.InitParams != null && e.InitParams.Count > 0)
{
controlid = e.InitParams[“ctlid”];
}
// Load the main control
this.RootVisual = new Page(controlid);

  • It is the ASP.NET server control (the host container for the Silverlight 2 application) that communicates with the PortalSiteMapProvider and the SharePoint Publishing API internally. It constructs an XML string with all of the navigation content that the Silverlight application must display. This is dropped in an XML Data Island in the page so that it can be picked up. The ID of the XML Data Island is passed as a value of the InitParameters property of the Silverlight control. This parameter is processed when the Silverlight application is starting. The code can be found in the code-behind for the app.xaml as part of the Application_Startup event handler.

Page.xaml.cs

This code-behind file contains all code for the functioning of the Silverlight application.

  • Open the Page.xaml.cs code behind file and modify the constructor:

public Page(string controlid){….}

  • The code defines a variable of type ObservableCollection. This collection will contain all page items that are retrieved from the SharePoint site. This type of collection class provides notification when items get added or removed

ObservableCollection<PageInfo> pages = null;

  • The constructor accepts the incoming ID of the XML Data Island and retrieves the XML by working with the HtmlPage class that gives you access to the HTML DOM. Once you have found the HtmlElement representing the XML Data Island, you extract the XML contained within it via the GetProperty method asking for the value of the innerHTML attribute. Then the ProcessXML method is called.

if (controlid != null)
{
HtmlElement ctl = HtmlPage.Document.GetElementById(controlid);
if (ctl != null)
xmlstring = (string)ctl.GetProperty(“innerHTML”);
}

  • The method ProcessXML uses System.Xml.XmlReader to parse the XML, to filter out all of the needed details and to store them in a local collection of PageInfo objects.

  • Create a new PageInfo instance and pass the values to this instance and add it to the ObservableCollection<PageInfo>

PageInfo page = new PageInfo();
reader.MoveToAttribute(“Title”);
page.Title = reader.Value;
reader.MoveToAttribute(“Url”);
page.Url = reader.Value;
reader.MoveToAttribute(“Description”);
page.Description = reader.Value;
reader.MoveToAttribute(“Image”);
page.ImageUrl = reader.Value;
pages.Add(page);

  • When the parsing finishes, the collection of PageInfo objects is assigned to the ItemSource property of the custom list box.

if (pages != null && pages.Count > 0)
{
MenuListBox.ItemsSource = pages;
}

  • Create a SelectionChanged method, when a User wants to navigate to a specific page in the MenuListBox

private void MenuListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
PageInfo page = (PageInfo)e.AddedItems[0];
HtmlPage.Window.Navigate(new Uri(page.Url, UriKind.RelativeOrAbsolute));

}

Now it is time to design the Silverlight controls

The app.xaml defines the styles and templates used by the Silverlight application. They are all defined within the Application.Resources tag

A VisualStateManager, which is new for Silverlight beta 2, is a mechanism for customizing the dynamic aspect of a control’s appearance. Control templates are defined in XAML. It defines the static structure of the control user interface. But most controls change their appearance when the user interacts with them, for example when the user hovers over a control or when the user clicks the control. When a user places the mouse over a control the control changes from one state to another.

Source:

http://www.codeplex.com/SL4SP/Release/ProjectReleases.aspx?ReleaseId=16420

MOSS-2007-WCMS-development-PortalSiteMapProvider-SiteMapNodeCollection-SiteMapNode-SPNavigationNodeCollection-SPNavigationNode-and-IsVisible

http://blogs.msdn.com/ecm/archive/2007/05/23/increased-performance-for-moss-apps-using-the-portalsitemapprovider.aspx

http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.navigation.portalsitemapprovider_members.aspx

Advertisements

One Response to “Custom Silverlight Navigation with the SP PortalSiteMapProvider”

  1. RRaveen said

    Dear Friends,

    I hope you are doing well. I have launched a web site http://www.codegain.com and it is basically aimed C#,JAVA,VB.NET,ASP.NET,AJAX,Sql Server,Oracle,WPF,WCF and etc resources, programming help, articles, code snippet, video demonstrations and problems solving support. I would like to invite you as an author and a supporter. Looking forward to hearing from you and hope you will join with us soon.

    Please forward this email to all of your friends who are related IT. Send to us your feed about site also.

    Thank you
    RRaveen
    Founder CodeGain.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: