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)
34 using System.Collections;
35 using System.ComponentModel;
36 using System.Web.UI.HtmlControls;
38 namespace System.Web.UI.WebControls
40 [Designer ("System.Web.UI.Design.WebControls.SiteMapPathDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
41 public class SiteMapPath: CompositeControl
43 SiteMapProvider provider;
45 Style currentNodeStyle;
47 Style pathSeparatorStyle;
50 ITemplate currentNodeTemplate;
51 ITemplate nodeTemplate;
52 ITemplate pathSeparatorTemplate;
53 ITemplate rootNodeTemplate;
55 private static readonly object ItemCreatedEvent = new object();
56 private static readonly object ItemDataBoundEvent = new object();
58 public event SiteMapNodeItemEventHandler ItemCreated {
59 add { Events.AddHandler (ItemCreatedEvent, value); }
60 remove { Events.RemoveHandler (ItemCreatedEvent, value); }
63 public event SiteMapNodeItemEventHandler ItemDataBound {
64 add { Events.AddHandler (ItemDataBoundEvent, value); }
65 remove { Events.RemoveHandler (ItemDataBoundEvent, value); }
68 protected virtual void OnItemCreated (SiteMapNodeItemEventArgs e)
71 SiteMapNodeItemEventHandler eh = (SiteMapNodeItemEventHandler) Events [ItemCreatedEvent];
72 if (eh != null) eh (this, e);
76 protected virtual void OnItemDataBound (SiteMapNodeItemEventArgs e)
79 SiteMapNodeItemEventHandler eh = (SiteMapNodeItemEventHandler) Events [ItemDataBoundEvent];
80 if (eh != null) eh (this, e);
84 [DefaultValueAttribute (null)]
85 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
86 [NotifyParentPropertyAttribute (true)]
87 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
88 public Style CurrentNodeStyle {
90 if (currentNodeStyle == null) {
91 currentNodeStyle = new Style ();
92 if (IsTrackingViewState)
93 ((IStateManager)currentNodeStyle).TrackViewState ();
95 return currentNodeStyle;
100 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
101 [PersistenceMode (PersistenceMode.InnerProperty)]
103 public virtual ITemplate CurrentNodeTemplate {
104 get { return currentNodeTemplate; }
105 set { currentNodeTemplate = value; UpdateControls (); }
108 [DefaultValueAttribute (null)]
109 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
110 [NotifyParentPropertyAttribute (true)]
111 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
112 public Style NodeStyle {
114 if (nodeStyle == null) {
115 nodeStyle = new Style ();
116 if (IsTrackingViewState)
117 ((IStateManager)nodeStyle).TrackViewState ();
123 [DefaultValue (null)]
124 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
125 [PersistenceMode (PersistenceMode.InnerProperty)]
127 public virtual ITemplate NodeTemplate {
128 get { return nodeTemplate; }
129 set { nodeTemplate = value; UpdateControls (); }
132 [DefaultValueAttribute (-1)]
133 [ThemeableAttribute (false)]
134 public virtual int ParentLevelsDisplayed {
135 get { return ViewState.GetInt ("ParentLevelsDisplayed", -1); }
137 if (value < -1) throw new ArgumentOutOfRangeException ("value");
138 ViewState ["ParentLevelsDisplayed"] = value;
143 [DefaultValueAttribute (PathDirection.RootToCurrent)]
144 public virtual PathDirection PathDirection {
145 get { return (PathDirection)ViewState.GetInt ("PathDirection", (int)PathDirection.RootToCurrent); }
147 if (value != PathDirection.RootToCurrent && value != PathDirection.CurrentToRoot)
148 throw new ArgumentOutOfRangeException ("value");
149 ViewState ["PathDirection"] = value;
154 [DefaultValueAttribute (" > ")]
155 [LocalizableAttribute (true)]
156 public virtual string PathSeparator {
157 get { return ViewState.GetString ("PathSeparator", " > "); }
159 ViewState ["PathSeparator"] = value;
164 [DefaultValueAttribute (null)]
165 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
166 [NotifyParentPropertyAttribute (true)]
167 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
168 public Style PathSeparatorStyle {
170 if (pathSeparatorStyle == null) {
171 pathSeparatorStyle = new Style ();
172 if (IsTrackingViewState)
173 ((IStateManager)pathSeparatorStyle).TrackViewState ();
175 return pathSeparatorStyle;
179 [DefaultValue (null)]
180 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
181 [PersistenceMode (PersistenceMode.InnerProperty)]
183 public virtual ITemplate PathSeparatorTemplate {
184 get { return pathSeparatorTemplate; }
185 set { pathSeparatorTemplate = value; UpdateControls (); }
188 [BrowsableAttribute (false)]
189 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
190 public SiteMapProvider Provider {
192 if (provider == null) {
193 if (this.SiteMapProvider.Length == 0) {
194 provider = SiteMap.Provider;
195 if (provider == null)
196 throw new HttpException ("There is no default provider configured for the site.");
198 provider = SiteMap.Providers [this.SiteMapProvider];
199 if (provider == null)
200 throw new HttpException ("SiteMap provider '" + this.SiteMapProvider + "' not found.");
211 [DefaultValueAttribute (false)]
212 public virtual bool RenderCurrentNodeAsLink {
213 get { return ViewState.GetBool ("RenderCurrentNodeAsLink", false); }
215 ViewState ["RenderCurrentNodeAsLink"] = value;
220 [DefaultValueAttribute (null)]
221 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
222 [NotifyParentPropertyAttribute (true)]
223 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
224 public Style RootNodeStyle {
226 if (rootNodeStyle == null) {
227 rootNodeStyle = new Style ();
228 if (IsTrackingViewState)
229 ((IStateManager)rootNodeStyle).TrackViewState ();
231 return rootNodeStyle;
235 [DefaultValue (null)]
236 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
237 [PersistenceMode (PersistenceMode.InnerProperty)]
239 public virtual ITemplate RootNodeTemplate {
240 get { return rootNodeTemplate; }
241 set { rootNodeTemplate = value; UpdateControls (); }
244 [DefaultValueAttribute (true)]
245 [ThemeableAttribute (false)]
246 public virtual bool ShowToolTips {
247 get { return ViewState.GetBool ("ShowToolTips", true); }
249 ViewState ["ShowToolTips"] = value;
254 [DefaultValueAttribute ("")]
255 [ThemeableAttribute (false)]
256 public virtual string SiteMapProvider {
257 get { return ViewState.GetString ("SiteMapProvider", ""); }
259 ViewState ["SiteMapProvider"] = value;
265 public virtual string SkipLinkText
267 get { return ViewState.GetString ("SkipLinkText", "Skip Navigation Links"); }
268 set { ViewState["SkipLinkText"] = value; }
272 void UpdateControls ()
274 ChildControlsCreated = false;
277 public override void DataBind ()
281 /* the child controls get bound in
283 foreach (Control c in Controls) {
284 if (c is SiteMapNodeItem) {
285 SiteMapNodeItem it = (SiteMapNodeItem)c;
286 OnItemDataBound (new SiteMapNodeItemEventArgs (it));
291 protected internal override void CreateChildControls ()
294 CreateControlHierarchy ();
298 protected virtual void CreateControlHierarchy ()
300 ArrayList nodes = new ArrayList ();
301 SiteMapNode node = Provider.CurrentNode;
302 if (node == null) return;
304 int levels = ParentLevelsDisplayed != -1 ? ParentLevelsDisplayed + 1 : int.MaxValue;
306 while (node != null && levels > 0) {
307 if (nodes.Count > 0) {
308 SiteMapNodeItem sep = new SiteMapNodeItem (nodes.Count, SiteMapNodeItemType.PathSeparator);
309 InitializeItem (sep);
310 SiteMapNodeItemEventArgs sargs = new SiteMapNodeItemEventArgs (sep);
311 OnItemCreated (sargs);
315 SiteMapNodeItemType nt;
316 if (nodes.Count == 0)
317 nt = SiteMapNodeItemType.Current;
318 else if (node.ParentNode == null)
319 nt = SiteMapNodeItemType.Root;
321 nt = SiteMapNodeItemType.Parent;
323 SiteMapNodeItem it = new SiteMapNodeItem (nodes.Count, nt);
324 it.SiteMapNode = node;
327 SiteMapNodeItemEventArgs args = new SiteMapNodeItemEventArgs (it);
328 OnItemCreated (args);
331 node = node.ParentNode;
335 if (PathDirection == PathDirection.RootToCurrent) {
336 for (int n=nodes.Count - 1; n>=0; n--)
337 Controls.Add ((Control)nodes[n]);
339 for (int n=0; n<nodes.Count; n++)
340 Controls.Add ((Control)nodes[n]);
344 protected virtual void InitializeItem (SiteMapNodeItem item)
346 switch (item.ItemType) {
347 case SiteMapNodeItemType.Root:
348 if (RootNodeTemplate != null) {
349 item.ApplyStyle (NodeStyle);
350 item.ApplyStyle (RootNodeStyle);
351 RootNodeTemplate.InstantiateIn (item);
353 else if (NodeTemplate != null) {
354 item.ApplyStyle (NodeStyle);
355 item.ApplyStyle (RootNodeStyle);
356 NodeTemplate.InstantiateIn (item);
359 WebControl c = CreateHyperLink (item);
360 c.ApplyStyle (NodeStyle);
361 c.ApplyStyle (RootNodeStyle);
362 item.Controls.Add (c);
366 case SiteMapNodeItemType.Current:
367 if (CurrentNodeTemplate != null) {
368 item.ApplyStyle (NodeStyle);
369 item.ApplyStyle (CurrentNodeStyle);
370 CurrentNodeTemplate.InstantiateIn (item);
372 else if (NodeTemplate != null) {
373 item.ApplyStyle (NodeStyle);
374 item.ApplyStyle (CurrentNodeStyle);
375 NodeTemplate.InstantiateIn (item);
376 } else if (RenderCurrentNodeAsLink) {
\r
377 HyperLink c = CreateHyperLink (item);
\r
378 c.ApplyStyle (NodeStyle);
\r
379 c.ApplyStyle (CurrentNodeStyle);
\r
380 item.Controls.Add (c);
\r
382 Literal c = CreateLiteral (item);
\r
383 item.ApplyStyle (NodeStyle);
\r
384 item.ApplyStyle (CurrentNodeStyle);
\r
385 item.Controls.Add (c);
\r
389 case SiteMapNodeItemType.Parent:
390 if (NodeTemplate != null) {
391 item.ApplyStyle (NodeStyle);
392 NodeTemplate.InstantiateIn (item);
395 WebControl c = CreateHyperLink (item);
396 c.ApplyStyle (NodeStyle);
397 item.Controls.Add (c);
401 case SiteMapNodeItemType.PathSeparator:
402 if (PathSeparatorTemplate != null) {
403 item.ApplyStyle (PathSeparatorStyle);
404 PathSeparatorTemplate.InstantiateIn (item);
407 Literal h = new Literal ();
408 h.Text = PathSeparator;
\r
409 item.ApplyStyle (PathSeparatorStyle);
\r
410 item.Controls.Add (h);
\r
416 HyperLink CreateHyperLink (SiteMapNodeItem item)
418 HyperLink h = new HyperLink ();
419 h.Text = item.SiteMapNode.Title;
420 h.NavigateUrl = item.SiteMapNode.Url;
422 h.ToolTip = item.SiteMapNode.Description;
426 Literal CreateLiteral (SiteMapNodeItem item)
\r
428 Literal h = new Literal ();
\r
429 h.Text = item.SiteMapNode.Title;
\r
433 protected override void LoadViewState (object savedState)
435 if (savedState == null) {
436 base.LoadViewState (null);
440 object[] states = (object[]) savedState;
441 base.LoadViewState (states [0]);
443 if (states[1] != null) ((IStateManager)CurrentNodeStyle).LoadViewState (states[1]);
444 if (states[2] != null) ((IStateManager)NodeStyle).LoadViewState (states[2]);
445 if (states[3] != null) ((IStateManager)PathSeparatorStyle).LoadViewState (states[3]);
446 if (states[4] != null) ((IStateManager)RootNodeStyle).LoadViewState (states[4]);
449 [MonoTODO ("why override?")]
450 protected override void OnDataBinding (EventArgs e)
452 base.OnDataBinding (e);
455 [MonoTODO ("why override?")]
456 protected internal override void Render (HtmlTextWriter w)
461 protected internal override void RenderContents (HtmlTextWriter w)
463 string skip_id = ClientID + "_SkipLink";
465 if (SkipLinkText != "") {
466 HtmlAnchor anchor = new HtmlAnchor ();
467 anchor.HRef = "#" + skip_id;
469 Image img = new Image ();
470 img.ImageUrl = Page.ClientScript.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif");
\r
471 img.Attributes.Add ("height", "0");
\r
472 img.Attributes.Add ("width", "0");
473 img.AlternateText = SkipLinkText;
\r
475 anchor.Controls.Add (img);
480 base.RenderContents (w);
482 if (SkipLinkText != "") {
483 HtmlAnchor anchor = new HtmlAnchor ();
489 protected override object SaveViewState ()
491 object[] state = new object [5];
492 state [0] = base.SaveViewState ();
494 if (currentNodeStyle != null) state [1] = ((IStateManager)currentNodeStyle).SaveViewState ();
495 if (nodeStyle != null) state [2] = ((IStateManager)nodeStyle).SaveViewState ();
496 if (pathSeparatorStyle != null) state [3] = ((IStateManager)pathSeparatorStyle).SaveViewState ();
497 if (rootNodeStyle != null) state [4] = ((IStateManager)rootNodeStyle).SaveViewState ();
499 for (int n=0; n<state.Length; n++)
500 if (state [n] != null) return state;
504 protected override void TrackViewState ()
506 base.TrackViewState();
507 if (currentNodeStyle != null) ((IStateManager)currentNodeStyle).TrackViewState();
508 if (nodeStyle != null) ((IStateManager)nodeStyle).TrackViewState();
509 if (pathSeparatorStyle != null) ((IStateManager)pathSeparatorStyle).TrackViewState();
510 if (rootNodeStyle != null) ((IStateManager)rootNodeStyle).TrackViewState();