我们常常习惯用TreeView在做导航栏,但是我们也希望不同权限的用户导航内用不用,以下是我一个例子。该例子是建立在vs2008 3.5的框架上的,沿用我自己的一个Framework框架。
1 我们建立Navigation.xml作为导航信息如:
<?xml version="1.0" encoding="utf-8" ?>
<TreeNode text="系统导航" value="01" description="系统导航" url="Default.aspx">
<TreeNode text="权限管理" value="01" description="权限管理" url="Admin/ManagerRole.aspx"/>
<TreeNode text="常量管理" value="0101" description="常量管理" url="Admin/ManageCodeTables.aspx"/>
<TreeNode text="异常管理" value="020101" description="异常管理" url="Admin/ExceptionLogViewer.aspx"/>
</TreeNode>
注意说明的是value是权限ID
模式文件
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="TreeNode">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="TreeNode">
<xs:complexType>
<xs:attribute name="text" type="xs:string" use="required" />
<xs:attribute name="value" type="xs:unsignedShort" use="required" />
<xs:attribute name="description" type="xs:string" use="required" />
<xs:attribute name="url" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="text" type="xs:string" use="required" />
<xs:attribute name="value" type="xs:unsignedByte" use="required" />
<xs:attribute name="description" type="xs:string" use="required" />
<xs:attribute name="url" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
2 读取文件并初始化TreeView 注意需要用到递归
public static void SetTreeViewNavigation(this TreeView tree, string fileName)
{
tree.SetTreeViewNavigation(fileName, string.Empty);
}
public static void SetTreeViewNavigation(this TreeView tree, string xmlFilePath, string schemaFilePath)
{
if (!xmlFilePath.Contains("://"))
xmlFilePath =AppDomain.CurrentDomain.BaseDirectory+ xmlFilePath;
if (string.IsNullOrEmpty(schemaFilePath))
{
schemaFilePath = AppDomain.CurrentDomain.BaseDirectory+"Navigation.xsd";
}
else
{
if (!schemaFilePath.Contains("://"))
schemaFilePath = AppDomain.CurrentDomain.BaseDirectory+schemaFilePath;
}
XDocument doc = XDocument.Load(xmlFilePath);
XmlSchemaSet schema = new XmlSchemaSet();
schema.Add(null, schemaFilePath);
doc.Validate(schema, (o, e) =>
{
if (e.Exception != null)
{
string message = xmlFilePath + " 不符合模式文件 " + schemaFilePath + " " + e.Message;
throw new Exception(message);
}
});
XElement root = doc.Root;
TreeNode node = new TreeNode
{
Text = root.Attribute("text").Value,
Value = root.Attribute("value").Value,
ToolTip = root.Attribute("description").Value,
NavigateUrl = root.Attribute("url").Value,
};
tree.Nodes.Add(node);
SetTreeViewNavigation(node, root, tree);
tree.TreeNodeCheckChanged += (sender, e) =>
{
if (e.Node != null && e.Node.NavigateUrl.Length > 0)
tree.Page.Server.Transfer(e.Node.NavigateUrl);
};
}
private static void SetTreeViewNavigation(TreeNode node, XElement element,TreeView tree)
{
if (element.HasElements)
{
var nodes = element.Elements("TreeNode");
foreach (XElement item in nodes)
{
TreeNode newnode = new TreeNode
{
Text = item.Attribute("text").Value,
Value = item.Attribute("value").Value,
ToolTip = item.Attribute("description").Value,
NavigateUrl = item.Attribute("url").Value,
};
if (tree.Page.HasPermission(newnode.Value))
{
node.ChildNodes.Add(newnode);
SetTreeViewNavigation(newnode, item, tree);
}
}
}
}
注意HasPermission这个方法是我自己扩展的,用来判断当前登录用户使用具有相应的权限,如果有才把该节点加到TreeView中。
3 由于多页面都存在这样的导航栏,因此我们用MasterPage
前台:
<asp:TreeView ID="TreeViewNavigation" runat="server" ImageSet="Events">
<ParentNodeStyle Font-Bold="False" />
<HoverNodeStyle Font-Underline="False" ForeColor="Red" />
<SelectedNodeStyle Font-Underline="True" HorizontalPadding="0px" VerticalPadding="0px" />
<NodeStyle Font-Names="Verdana" Font-Size="8pt" ForeColor="Black" HorizontalPadding="5px"
NodeSpacing="0px" VerticalPadding="0px" />
</asp:TreeView>
后台:
if (!this.IsPostBack)
{
CacheManager cacheManager = CacheFactory.GetCacheManager();
string key = Constants.FrameworkConstants.TreeViewNavigation + Convert.ToString(this.Page.GetRoleID());
if (cacheManager[key] == null)
{
TreeViewNavigation.SetTreeViewNavigation("Navigation.xml");
cacheManager.Add(key, TreeViewNavigation.Nodes[0]);
}
else
{
TreeNode node = cacheManager[key] as TreeNode;
TreeViewNavigation.Nodes.Add(node);
}
}
OnChangedRoleID += (o, n) =>
{
CacheManager cacheManager = CacheFactory.GetCacheManager();
string key = Constants.FrameworkConstants.TreeViewNavigation + o;
cacheManager.Remove(key);
};
为了让第二个页面加载TreeView不再去查询相应的权限,我把先前用户的treeNode保存起来艺提高性能。CacheManager 也是我框架建立好了的。但是一旦用户角色改变就需要改变内存中的一些数据
public delegate void ChangedRoleID(string oldRoleID, string newRoleID);
ChangedRoleID OnChangedRoleID;
public string CurrentRoleID
{
set
{
string oleID= CurrentRoleID;
Session[Constants.FrameworkConstants.CurrentRoleID] = value;
WriteCookie(Constants.FrameworkConstants.CurrentRoleID, value, 60 * 24);
if (OnChangedRoleID != null && !oleID.Equals(value))
OnChangedRoleID(oleID, value);
}
get
{
if (Session[Constants.FrameworkConstants.CurrentRoleID] != null)
return Session[Constants.FrameworkConstants.CurrentRoleID].ToString();
string temp = GetCookie(Constants.FrameworkConstants.CurrentRoleID);
if (temp.Length > 0)
{
Session[Constants.FrameworkConstants.CurrentRoleID] = temp;
return temp;
}
return string.Empty;
}
}