2 // System.Web.UI.WebControls.SiteMapPath.cs
5 // Lluis Sanchez Gual (lluis@novell.com)
7 // (C) 2005 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
33 using System.Collections;
34 using System.ComponentModel;
35 using System.Web.UI.HtmlControls;
37 namespace System.Web.UI.WebControls
39 [Designer ("System.Web.UI.Design.WebControls.SiteMapPathDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
40 public class SiteMapPath: CompositeControl
42 SiteMapProvider provider;
44 Style currentNodeStyle;
46 Style pathSeparatorStyle;
49 ITemplate currentNodeTemplate;
50 ITemplate nodeTemplate;
51 ITemplate pathSeparatorTemplate;
52 ITemplate rootNodeTemplate;
54 static readonly object ItemCreatedEvent = new object();
55 static readonly object ItemDataBoundEvent = new object();
57 public event SiteMapNodeItemEventHandler ItemCreated {
58 add { Events.AddHandler (ItemCreatedEvent, value); }
59 remove { Events.RemoveHandler (ItemCreatedEvent, value); }
62 public event SiteMapNodeItemEventHandler ItemDataBound {
63 add { Events.AddHandler (ItemDataBoundEvent, value); }
64 remove { Events.RemoveHandler (ItemDataBoundEvent, value); }
67 protected virtual void OnItemCreated (SiteMapNodeItemEventArgs e)
70 SiteMapNodeItemEventHandler eh = (SiteMapNodeItemEventHandler) Events [ItemCreatedEvent];
71 if (eh != null) eh (this, e);
75 protected virtual void OnItemDataBound (SiteMapNodeItemEventArgs e)
78 SiteMapNodeItemEventHandler eh = (SiteMapNodeItemEventHandler) Events [ItemDataBoundEvent];
79 if (eh != null) eh (this, e);
83 [DefaultValueAttribute (null)]
84 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
85 [NotifyParentPropertyAttribute (true)]
86 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
87 public Style CurrentNodeStyle {
89 if (currentNodeStyle == null) {
90 currentNodeStyle = new Style ();
91 if (IsTrackingViewState)
92 ((IStateManager)currentNodeStyle).TrackViewState ();
94 return currentNodeStyle;
99 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
100 [PersistenceMode (PersistenceMode.InnerProperty)]
102 public virtual ITemplate CurrentNodeTemplate {
103 get { return currentNodeTemplate; }
104 set { currentNodeTemplate = value; UpdateControls (); }
107 [DefaultValueAttribute (null)]
108 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
109 [NotifyParentPropertyAttribute (true)]
110 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
111 public Style NodeStyle {
113 if (nodeStyle == null) {
114 nodeStyle = new Style ();
115 if (IsTrackingViewState)
116 ((IStateManager)nodeStyle).TrackViewState ();
122 [DefaultValue (null)]
123 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
124 [PersistenceMode (PersistenceMode.InnerProperty)]
126 public virtual ITemplate NodeTemplate {
127 get { return nodeTemplate; }
128 set { nodeTemplate = value; UpdateControls (); }
131 [DefaultValueAttribute (-1)]
132 [ThemeableAttribute (false)]
133 public virtual int ParentLevelsDisplayed {
134 get { return ViewState.GetInt ("ParentLevelsDisplayed", -1); }
136 if (value < -1) throw new ArgumentOutOfRangeException ("value");
137 ViewState ["ParentLevelsDisplayed"] = value;
142 [DefaultValueAttribute (PathDirection.RootToCurrent)]
143 public virtual PathDirection PathDirection {
144 get { return (PathDirection)ViewState.GetInt ("PathDirection", (int)PathDirection.RootToCurrent); }
146 if (value != PathDirection.RootToCurrent && value != PathDirection.CurrentToRoot)
147 throw new ArgumentOutOfRangeException ("value");
148 ViewState ["PathDirection"] = value;
153 [DefaultValueAttribute (" > ")]
154 [LocalizableAttribute (true)]
155 public virtual string PathSeparator {
156 get { return ViewState.GetString ("PathSeparator", " > "); }
158 ViewState ["PathSeparator"] = value;
163 [DefaultValueAttribute (null)]
164 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
165 [NotifyParentPropertyAttribute (true)]
166 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
167 public Style PathSeparatorStyle {
169 if (pathSeparatorStyle == null) {
170 pathSeparatorStyle = new Style ();
171 if (IsTrackingViewState)
172 ((IStateManager)pathSeparatorStyle).TrackViewState ();
174 return pathSeparatorStyle;
178 [DefaultValue (null)]
179 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
180 [PersistenceMode (PersistenceMode.InnerProperty)]
182 public virtual ITemplate PathSeparatorTemplate {
183 get { return pathSeparatorTemplate; }
184 set { pathSeparatorTemplate = value; UpdateControls (); }
187 [BrowsableAttribute (false)]
188 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
189 public SiteMapProvider Provider {
191 if (provider == null) {
192 if (this.SiteMapProvider.Length == 0) {
193 provider = SiteMap.Provider;
194 if (provider == null)
195 throw new HttpException ("There is no default provider configured for the site.");
197 provider = SiteMap.Providers [this.SiteMapProvider];
198 if (provider == null)
199 throw new HttpException ("SiteMap provider '" + this.SiteMapProvider + "' not found.");
210 [DefaultValueAttribute (false)]
211 public virtual bool RenderCurrentNodeAsLink {
212 get { return ViewState.GetBool ("RenderCurrentNodeAsLink", false); }
214 ViewState ["RenderCurrentNodeAsLink"] = value;
219 [DefaultValueAttribute (null)]
220 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
221 [NotifyParentPropertyAttribute (true)]
222 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
223 public Style RootNodeStyle {
225 if (rootNodeStyle == null) {
226 rootNodeStyle = new Style ();
227 if (IsTrackingViewState)
228 ((IStateManager)rootNodeStyle).TrackViewState ();
230 return rootNodeStyle;
234 [DefaultValue (null)]
235 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
236 [PersistenceMode (PersistenceMode.InnerProperty)]
238 public virtual ITemplate RootNodeTemplate {
239 get { return rootNodeTemplate; }
240 set { rootNodeTemplate = value; UpdateControls (); }
243 [DefaultValueAttribute (true)]
244 [ThemeableAttribute (false)]
245 public virtual bool ShowToolTips {
246 get { return ViewState.GetBool ("ShowToolTips", true); }
248 ViewState ["ShowToolTips"] = value;
253 [DefaultValueAttribute ("")]
254 [ThemeableAttribute (false)]
255 public virtual string SiteMapProvider {
256 get { return ViewState.GetString ("SiteMapProvider", ""); }
258 ViewState ["SiteMapProvider"] = value;
264 public virtual string SkipLinkText
266 get { return ViewState.GetString ("SkipLinkText", "Skip Navigation Links"); }
267 set { ViewState["SkipLinkText"] = value; }
271 void UpdateControls ()
273 ChildControlsCreated = false;
276 public override void DataBind ()
280 /* the child controls get bound in
282 foreach (Control c in Controls) {
283 if (c is SiteMapNodeItem) {
284 SiteMapNodeItem it = (SiteMapNodeItem)c;
285 OnItemDataBound (new SiteMapNodeItemEventArgs (it));
290 protected internal override void CreateChildControls ()
293 CreateControlHierarchy ();
297 protected virtual void CreateControlHierarchy ()
299 ArrayList nodes = new ArrayList ();
300 SiteMapNode node = Provider.CurrentNode;
301 if (node == null) return;
303 int levels = ParentLevelsDisplayed != -1 ? ParentLevelsDisplayed + 1 : int.MaxValue;
305 while (node != null && levels > 0) {
306 if (nodes.Count > 0) {
307 SiteMapNodeItem sep = new SiteMapNodeItem (nodes.Count, SiteMapNodeItemType.PathSeparator);
308 InitializeItem (sep);
309 SiteMapNodeItemEventArgs sargs = new SiteMapNodeItemEventArgs (sep);
310 OnItemCreated (sargs);
314 SiteMapNodeItemType nt;
315 if (nodes.Count == 0)
316 nt = SiteMapNodeItemType.Current;
317 else if (node.ParentNode == null)
318 nt = SiteMapNodeItemType.Root;
320 nt = SiteMapNodeItemType.Parent;
322 SiteMapNodeItem it = new SiteMapNodeItem (nodes.Count, nt);
323 it.SiteMapNode = node;
326 SiteMapNodeItemEventArgs args = new SiteMapNodeItemEventArgs (it);
327 OnItemCreated (args);
330 node = node.ParentNode;
334 if (PathDirection == PathDirection.RootToCurrent) {
335 for (int n=nodes.Count - 1; n>=0; n--)
336 Controls.Add ((Control)nodes[n]);
338 for (int n=0; n<nodes.Count; n++)
339 Controls.Add ((Control)nodes[n]);
343 protected virtual void InitializeItem (SiteMapNodeItem item)
345 switch (item.ItemType) {
346 case SiteMapNodeItemType.Root:
347 if (RootNodeTemplate != null) {
348 item.ApplyStyle (NodeStyle);
349 item.ApplyStyle (RootNodeStyle);
350 RootNodeTemplate.InstantiateIn (item);
352 else if (NodeTemplate != null) {
353 item.ApplyStyle (NodeStyle);
354 item.ApplyStyle (RootNodeStyle);
355 NodeTemplate.InstantiateIn (item);
358 WebControl c = CreateHyperLink (item);
359 c.ApplyStyle (NodeStyle);
360 c.ApplyStyle (RootNodeStyle);
361 item.Controls.Add (c);
365 case SiteMapNodeItemType.Current:
366 if (CurrentNodeTemplate != null) {
367 item.ApplyStyle (NodeStyle);
368 item.ApplyStyle (CurrentNodeStyle);
369 CurrentNodeTemplate.InstantiateIn (item);
371 else if (NodeTemplate != null) {
372 item.ApplyStyle (NodeStyle);
373 item.ApplyStyle (CurrentNodeStyle);
374 NodeTemplate.InstantiateIn (item);
375 } else if (RenderCurrentNodeAsLink) {
376 HyperLink c = CreateHyperLink (item);
377 c.ApplyStyle (NodeStyle);
378 c.ApplyStyle (CurrentNodeStyle);
379 item.Controls.Add (c);
381 Literal c = CreateLiteral (item);
382 item.ApplyStyle (NodeStyle);
383 item.ApplyStyle (CurrentNodeStyle);
384 item.Controls.Add (c);
388 case SiteMapNodeItemType.Parent:
389 if (NodeTemplate != null) {
390 item.ApplyStyle (NodeStyle);
391 NodeTemplate.InstantiateIn (item);
394 WebControl c = CreateHyperLink (item);
395 c.ApplyStyle (NodeStyle);
396 item.Controls.Add (c);
400 case SiteMapNodeItemType.PathSeparator:
401 if (PathSeparatorTemplate != null) {
402 item.ApplyStyle (PathSeparatorStyle);
403 PathSeparatorTemplate.InstantiateIn (item);
405 Literal h = new Literal ();
406 h.Text = HttpUtility.HtmlEncode (PathSeparator);
407 item.ApplyStyle (PathSeparatorStyle);
408 item.Controls.Add (h);
414 HyperLink CreateHyperLink (SiteMapNodeItem item)
416 HyperLink h = new HyperLink ();
417 h.Text = item.SiteMapNode.Title;
418 h.NavigateUrl = item.SiteMapNode.Url;
420 h.ToolTip = item.SiteMapNode.Description;
424 Literal CreateLiteral (SiteMapNodeItem item)
426 Literal h = new Literal ();
427 h.Text = item.SiteMapNode.Title;
431 protected override void LoadViewState (object savedState)
433 if (savedState == null) {
434 base.LoadViewState (null);
438 object[] states = (object[]) savedState;
439 base.LoadViewState (states [0]);
441 if (states[1] != null) ((IStateManager)CurrentNodeStyle).LoadViewState (states[1]);
442 if (states[2] != null) ((IStateManager)NodeStyle).LoadViewState (states[2]);
443 if (states[3] != null) ((IStateManager)PathSeparatorStyle).LoadViewState (states[3]);
444 if (states[4] != null) ((IStateManager)RootNodeStyle).LoadViewState (states[4]);
447 [MonoTODO ("why override?")]
448 protected override void OnDataBinding (EventArgs e)
450 base.OnDataBinding (e);
453 [MonoTODO ("why override?")]
454 protected internal override void Render (HtmlTextWriter w)
459 protected internal override void RenderContents (HtmlTextWriter w)
461 string skip_id = ClientID + "_SkipLink";
462 string altText = SkipLinkText;
463 bool needAnchor = !String.IsNullOrEmpty (altText);
467 w.AddAttribute (HtmlTextWriterAttribute.Href, "#" + skip_id);
468 w.RenderBeginTag (HtmlTextWriterTag.A);
471 w.AddAttribute (HtmlTextWriterAttribute.Alt, altText);
472 w.AddAttribute (HtmlTextWriterAttribute.Height, "0");
473 w.AddAttribute (HtmlTextWriterAttribute.Width, "0");
474 w.AddAttribute (HtmlTextWriterAttribute.Src, Page.ClientScript.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif"));
475 w.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0px");
476 w.RenderBeginTag (HtmlTextWriterTag.Img);
482 base.RenderContents (w);
485 w.AddAttribute(HtmlTextWriterAttribute.Id, skip_id);
486 w.RenderBeginTag(HtmlTextWriterTag.A);
491 protected override object SaveViewState ()
493 object[] state = new object [5];
494 state [0] = base.SaveViewState ();
496 if (currentNodeStyle != null) state [1] = ((IStateManager)currentNodeStyle).SaveViewState ();
497 if (nodeStyle != null) state [2] = ((IStateManager)nodeStyle).SaveViewState ();
498 if (pathSeparatorStyle != null) state [3] = ((IStateManager)pathSeparatorStyle).SaveViewState ();
499 if (rootNodeStyle != null) state [4] = ((IStateManager)rootNodeStyle).SaveViewState ();
501 for (int n=0; n<state.Length; n++)
502 if (state [n] != null) return state;
506 protected override void TrackViewState ()
508 base.TrackViewState();
509 if (currentNodeStyle != null) ((IStateManager)currentNodeStyle).TrackViewState();
510 if (nodeStyle != null) ((IStateManager)nodeStyle).TrackViewState();
511 if (pathSeparatorStyle != null) ((IStateManager)pathSeparatorStyle).TrackViewState();
512 if (rootNodeStyle != null) ((IStateManager)rootNodeStyle).TrackViewState();