SietMapProvider的用途
在VS2005中新增的SiteMapProvider是用來提供常見的網站的導覽(Site Navigation Provider)所對應的幾個顯示用UI元件:Menu、SiteMapPath、TreeView的資料提供者(DataProvider)。在VS2005中,透過SiteMapProvider或XML File的方式,我們可以將網頁導覽的資料定義在XML file或同樣是XML格式的.sitemap file中,在未來網站的導覽需要修改的時候,只要修改xml檔案,而不需要在變動到程式碼,節省維護上的時間。
動態建立SiteMapProvider
在上述的過程中,對於一般的網站建置來說,已經是非常方便的,但是如果今天我們是設計一個根據使用者的不同而分別列出不同的導覽範圍,或者SiteMap的資料是儲存在資料庫的時候,上述的功能就不符使用了。當然我們也可以把不同的使用者分別設計不同的xml file存放,但是這樣子反而造成維護上的負擔,這時候我們可以透過自己設計一個新的SiteMapProvider,在自定的SiteMapProvider中,我們可以自己規劃資料的來源去針對資料庫,或者根據當時使用者的資訊來從新建立SiteMap的資料。在MDSN中有一篇文章提到
How to: Implement ASP.NET Site-Map Providers,在其中有提供兩種解決方案,分別是
Example Text Site-Map Provider以及
Example Access Site-Map Provider,其中Access Site-Map就是一個從資料庫提取選單的好例子,整個程式範例可以全部複製過去參考,在Access Site-Map中,只需要把Method BuildSiteMap替換成自己的方法,就可以產生新的SiteMapProvider了,Text Site-Map Provider的例子反而太繁瑣所以不推薦。程式碼的部分有點雜,建議直接看一下。
// Build an in-memory representation from persistent
// storage, and return the root node of the site map.
public override SiteMapNode BuildSiteMap() {
// Since the SiteMap class is static, make sure that it is
// not modified while the site map is built.
lock(this) {
// If there is no initialization, this method is being
// called out of order.
if (! IsInitialized) {
throw new Exception("BuildSiteMap called incorrectly.");
}
// If there is no root node, then there is no site map.
if (null == rootNode) {
// Start with a clean slate
Clear();
// Select the root node of the site map from Microsoft Access.
int rootNodeId = -1;
if (accessConnection.State == ConnectionState.Closed)
accessConnection.Open();
OleDbCommand rootNodeCommand =
new OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid IS NULL",
accessConnection);
OleDbDataReader rootNodeReader = rootNodeCommand.ExecuteReader();
if(rootNodeReader.HasRows) {
rootNodeReader.Read();
rootNodeId = rootNodeReader.GetInt32(0);
// Create a SiteMapNode that references the current StaticSiteMapProvider.
// 這裡建立了rootNode,輸入的參數內容可以查MSDN。
rootNode = new SiteMapNode(this,
rootNodeId.ToString(),
rootNodeReader.GetString(1),
rootNodeReader.GetString(2));
}
else return null;
rootNodeReader.Close();
// Select the child nodes of the root node.
OleDbCommand childNodesCommand =
new OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?",
accessConnection);
OleDbParameter rootParam = new OleDbParameter("parentid", OleDbType.Integer);
rootParam.Value = rootNodeId;
childNodesCommand.Parameters.Add(rootParam);
OleDbDataReader childNodesReader = childNodesCommand.ExecuteReader();
if (childNodesReader.HasRows) {
SiteMapNode childNode = null;
while(childNodesReader.Read()) {
// 這裡建立了childNode。
childNode = new SiteMapNode(this,
childNodesReader.GetInt32(0).ToString(),
childNodesReader.GetString(1),
childNodesReader.GetString(2));
// Use the SiteMapNode AddNode method to add
// the SiteMapNode to the ChildNodes collection.
// 透過內建的AddNode,把childNode放在rootNode下,自己設計的時候只要
// 自己保留另一個parentNode的值,就可以階層化建立出n階的結構。
AddNode(childNode, rootNode);
}
}
childNodesReader.Close();
accessConnection.Close();
}
return rootNode;
}
}
沒有留言:
張貼留言