📄 basenavigator.cs
字号:
// TODO: fix up prev/next pointers
oNode.previousSibling = oPreviousNode;
if(oPreviousNode != null)
{
oPreviousNode.nextSibling = oNode;
}
oNode.nextSibling = null;
counter++;
// maybe we need to read some additional data?
if(oNode.nodes == null && oNode.SiteMapXmlFile != string.Empty)
{
LoadXmlNode(oNode, oNode.SiteMapXmlFile);
}
if(oNode.nodes != null)
{
counter = FixStructureStep(oNode, oNode.nodes, counter);
}
oPreviousNode = oNode;
}
return counter;
}
private void GetXml(XmlDocument oXmlDoc, XmlNode oXmlNode, NavigationNodeCollection arNodes)
{
foreach(NavigationNode oNode in arNodes)
{
XmlElement oNewElement = oXmlDoc.CreateElement("Node");
foreach(string sKey in oNode.Properties.Keys)
{
oNewElement.SetAttribute(sKey, oNode.Properties[sKey]);
}
oXmlNode.AppendChild(oNewElement);
if(oNode.nodes != null)
{
GetXml(oXmlDoc, oNewElement, oNode.nodes);
}
}
}
protected virtual void HandlePostback(string stringArgument)
{
return;
}
/// <summary>
/// Go through nodes, finding ones that reference templates, and
/// instantiate those templates using the nodes.
/// </summary>
/// <param name="arNodes">The nodes to begin searching from.</param>
private void InstantiateTemplatedNodes(NavigationNodeCollection arNodes)
{
foreach(NavigationNode oNode in arNodes)
{
if(oNode.ServerTemplateId != string.Empty)
{
NavigationCustomTemplate oTemplate = this.FindTemplateById(oNode.ServerTemplateId);
if(oTemplate == null)
{
throw new Exception("Template not found: " + oNode.ServerTemplateId);
}
NavigationTemplateContainer oContainer = new NavigationTemplateContainer(oNode);
oTemplate.Template.InstantiateIn(oContainer);
oContainer.ID = this.ClientID + "_" + oNode.PostBackID;
oContainer.DataBind();
this.Controls.Add(oContainer);
}
if(oNode.nodes != null)
{
InstantiateTemplatedNodes(oNode.nodes);
}
}
}
protected void LoadFromSiteMap(System.Web.SiteMapNode oRoot, bool bIncludeRoot)
{
if (bIncludeRoot)
{
NavigationNode oRootNode = this.AddNode();
this.LoadFromSiteMapNode(oRootNode, oRoot);
this.OnNodeDataBound(oRootNode, oRoot);
}
else
{
foreach (System.Web.SiteMapNode oNode in oRoot.ChildNodes)
{
NavigationNode oNavigationNode = this.AddNode();
this.LoadFromSiteMapNode(oNavigationNode, oNode);
this.OnNodeDataBound(oNavigationNode, oNode);
}
}
}
protected void LoadFromSiteMapNode(NavigationNode oNavigationNode, System.Web.SiteMapNode oNode)
{
oNavigationNode.NavigateUrl = oNode.Url;
oNavigationNode.Text = oNode.Title;
oNavigationNode.ToolTip = oNode.Description;
oNavigationNode.ID = oNode.Key;
// use attribute mappings to access additional properties
foreach (CustomAttributeMapping oMapping in this.CustomAttributeMappings)
{
string sValue = oNode[oMapping.From];
if (sValue != null)
{
oNavigationNode.Properties[oMapping.From] = sValue;
}
}
// load children
foreach (System.Web.SiteMapNode oChildNode in oNode.ChildNodes)
{
NavigationNode oChildNavigationNode = oNavigationNode.AddNode();
this.LoadFromSiteMapNode(oChildNavigationNode, oChildNode);
this.OnNodeDataBound(oChildNavigationNode, oChildNode);
}
}
protected void LoadXmlNode(NavigationNode oNavigationNode, string sXmlFile)
{
if(Context == null)
{
return;
}
string sServerPath = Context.Server.MapPath(sXmlFile);
if(!File.Exists(sServerPath))
{
throw new FileNotFoundException("File " + sServerPath + " does not exist.");
}
// Load XML from SiteMapXmlFile
XmlDocument oXmlDoc = new XmlDocument();
oXmlDoc.Load(sServerPath);
XmlNodeList arNodeList = oXmlDoc.DocumentElement.ChildNodes;
// Add roots and process their children recursively
foreach(XmlNode oNode in arNodeList)
{
// Only process Xml elements (ignore comments, etc)
if(oNode.NodeType == XmlNodeType.Element)
{
NavigationNode oNewNode = oNavigationNode.AddNode();
this.LoadXmlNode(oNewNode, oNode);
this.OnNodeDataBound(oNewNode, oNode);
}
}
}
protected void LoadXmlNode(NavigationNode oNavigationNode, XmlNode oXmlNode)
{
oNavigationNode.ReadXmlAttributes(oXmlNode.Attributes);
if(oNavigationNode.SiteMapXmlFile != string.Empty)
{
this.LoadXmlNode(oNavigationNode, oNavigationNode.SiteMapXmlFile);
}
else
{
// Add roots and process their children recursively
foreach(XmlNode oNode in oXmlNode.ChildNodes)
{
// Only process Xml elements (ignore comments, etc)
if(oNode.NodeType == XmlNodeType.Element)
{
NavigationNode oNewNode = oNavigationNode.AddNode();
this.LoadXmlNode(oNewNode, oNode);
this.OnNodeDataBound(oNewNode, oNode);
}
}
}
}
private void PopulateNodePreviousUrls()
{
if (this.nodes.Count > 0)
{
this._curPreviousUrl = null;
for (int i=0; i<this.nodes.Count; i++)
{
this.PopulateNodePreviousUrls(this.nodes[i]);
}
}
}
private string _curPreviousUrl;
private void PopulateNodePreviousUrls(NavigationNode curNode)
{
if (curNode.nodes != null)
{
for (int i=0; i<curNode.nodes.Count; i++)
{
NavigationNode childNode = curNode.nodes[i];
this.PopulateNodePreviousUrls(childNode);
}
}
curNode.previousUrl = this._curPreviousUrl;
if (curNode.NavigateUrl != null && curNode.NavigateUrl != String.Empty)
{
this._curPreviousUrl = curNode.NavigateUrl;
}
}
private void PopulateNodeNextUrls()
{
if (this.nodes.Count > 0)
{
this._curNextUrl = null;
for (int i=this.nodes.Count-1; i>=0; i--)
{
this.PopulateNodeNextUrls(this.nodes[i]);
}
}
}
private string _curNextUrl;
private void PopulateNodeNextUrls(NavigationNode curNode)
{
if (curNode.nodes != null)
{
for (int i=curNode.nodes.Count-1; i>=0; i--)
{
NavigationNode childNode = curNode.nodes[i];
this.PopulateNodeNextUrls(childNode);
}
}
curNode.nextUrl = this._curNextUrl;
if (curNode.NavigateUrl != null && curNode.NavigateUrl != String.Empty)
{
this._curNextUrl = curNode.NavigateUrl;
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if(Context != null && Page != null)
{
string dummy = Page.GetPostBackEventReference(this); // Ensure that __doPostBack is output to client side
}
// Do nothing if this isn't an initial run.
if(EnableViewState && Context != null && Page.IsPostBack)
return;
if (this.DataSourceID != "")
{
Control oControl = Utils.FindControl(this, this.DataSourceID);
if (oControl != null && oControl is SiteMapDataSource)
{
SiteMapDataSource oDS = (SiteMapDataSource)oControl;
this.LoadFromSiteMap(oDS.Provider.RootNode, oDS.ShowStartingNode);
}
else if (oControl != null && oControl is XmlDataSource)
{
XmlDataSource oDS = (XmlDataSource)oControl;
XmlDocument oXmlDoc = oDS.GetXmlDocument();
this.LoadXml(oXmlDoc);
}
else
{
throw new Exception("DataSourceID must be set to the ID of a SiteMapDataSource or XmlDataSource control.");
}
}
// at this point, we have the structure loaded.
ComponentArtFixStructure();
this.UpdateSelectedNode();
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if(ViewState["SiteMapXml"] != null)
{
this.LoadXml((string)ViewState["SiteMapXml"]);
bNewDataLoaded = true;
this.ComponentArtFixStructure();
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// do we have no content?
if((this.nodes == null || this.nodes.Count == 0) && this.SiteMapXmlFile != string.Empty && Context != null) // if we have an xml file, load it up
{
string sServerPath = Context.Server.MapPath(this.SiteMapXmlFile);
if(!File.Exists(sServerPath))
{
throw new FileNotFoundException("Specified SiteMapXmlFile does not exist.");
}
// Load XML from SiteMapXmlFile
XmlDocument oXmlDoc = new XmlDocument();
oXmlDoc.Load(sServerPath);
this.LoadXml(oXmlDoc);
if(this.nodes != null && this.nodes.Count > 0)
{
bNewDataLoaded = true;
}
}
// at this point, we have the structure loaded.
ComponentArtFixStructure();
this.UpdateSelectedNode();
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
// Persist tree structure
if(this.EnableViewState && !(this is BaseMenu) && !(this is TreeView))
{
ViewState["SiteMapXml"] = this.GetXml();
}
}
private void RenderCrawlerNodes(NavigationNodeCollection arNodes, HtmlTextWriter output)
{
foreach(NavigationNode oNode in arNodes)
{
if(oNode.NavigateUrl != string.Empty)
{
output.AddAttribute("href", oNode.NavigateUrl);
output.RenderBeginTag(HtmlTextWriterTag.A);
output.Write(oNode.Text);
output.RenderEndTag(); // </a>
}
if(oNode.nodes != null)
{
RenderCrawlerNodes(oNode.nodes, output);
}
}
}
protected void RenderCrawlerStructure(HtmlTextWriter output)
{
output.RenderBeginTag(HtmlTextWriterTag.Noscript);
if(this.nodes != null && this.nodes.Count > 0)
{
RenderCrawlerNodes(this.nodes, output);
}
output.RenderEndTag();
}
protected void RenderPreloadImages(HtmlTextWriter output)
{
output.Write("<div style=\"position:absolute;top:0px;left:0px;visibility:hidden;\">");
foreach(string sImage in this.PreloadImages)
{
output.Write("<img src=\"" + sImage + "\" width=\"0\" height=\"0\" alt=\"\" />\n");
}
output.Write("</div>");
}
// This method determines which NavNode should be designated as the SelectedNode
protected void UpdateSelectedNode()
{
if(Context == null || Page == null)
{
// do nothing
return;
}
if (Page.Request.HttpMethod == "POST")
{
string sEventTarget = Page.Request.Params["__EVENTTARGET"];
if(sEventTarget != null && sEventTarget != string.Empty && this.ClientID == sEventTarget)
{
if(this.selectedNode == null)
{
string postbackNodeId = Page.Request.Params["__EVENTARGUMENT"];
if(postbackNodeId != null && postbackNodeId != string.Empty)
{
NavigationNode itemThatCausedPostback = FindNodeByPostBackId(postbackNodeId, this.nodes);
this.selectedNode = itemThatCausedPostback;
}
}
}
}
// try the regular means of finding the selected node
if(selectedNode == null)
{
NavigationNode oFoundNode = FindSelectedNode();
if(oFoundNode != null)
{
this.selectedNode = oFoundNode;
}
}
}
#region Logic for finding the current node
/* Algorithm for picking the SelectedNode when page is not a postback (when it's an HTTP GET).
* (Looking for the item with the URL that best corresponds to the URL of the current request.)
*
* URL match quality, from best to worst:
*
* a) Node's URL points to the same file as the current request and has an identical query string
* b) Node's URL points to the same file as the current request, its query params are a subset of
* the query params of the current request, and no menu item has a bigger matching subset of params.
* (This means that the node's URL can include all the query params, some of the params, or none of
* the params, and the ordering of the params in the query string never matters.)
* c) All else is not a match. (Node doesn't have a URL, or the URL doesn't point to the same file
* as the current request, or it contains some query parameters not found in the request.)
*
* Note: paths are case-insensitive, query strings are case-sensitive. */
private NavigationNode bestMatchItemNode = null;
private bool bestMatchQueryIdentical = false;
private int bestMatchQueryParamsMatched = -1;
protected NavigationNode FindSelectedNode()
{
// Reset the bestMatch data for the brand-new search:
bestMatchItemNode = null;
bestMatchQueryIdentical = false;
bestMatchQueryParamsMatched = -1; // not applicable
// Let's search:
if(this.RenderRootNodeId != string.Empty)
{
NavigationNode oRootNode = this.FindNodeById(this.RenderRootNodeId);
if(oRootNode != null && oRootNode.nodes != null)
{
SearchForSelectedNode(oRootNode.nodes);
}
if(bestMatchItemNode == null)
{
SearchForSelectedNode(nodes);
}
}
else
{
SearchForSelectedNode(nodes);
}
return bestMatchItemNode;
}
// Recursively search through the given group looking for the item w
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -