VS2005中自己带了一个Treeview控件,可以不再使用Microsoft命名空间的那个了,本来是件好事。
可我用来用去反而觉得这个新的Treeview控件用起来特bt。
下面我就说说我用这个控件的曲折经历吧,也许是我天资不够聪明才会这样,惭愧啊!
数据源绑定:
我用到了两种方法。
一种是从表中循环获取,下面是msdn上的例子:
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">
void PopulateNode(Object sender, TreeNodeEventArgs e)
{
// Call the appropriate method to populate a node at a particular level.
switch(e.Node.Depth)
{
case 0:
// Populate the first-level nodes.
PopulateCategories(e.Node);
break;
case 1:
// Populate the second-level nodes.
PopulateProducts(e.Node);
break;
default:
// Do nothing.
break;
}
}
void PopulateCategories(TreeNode node)
{
// Query for the product categories. These are the values
// for the second-level nodes.
DataSet ResultSet = RunQuery("Select CategoryID, CategoryName From Categories");
// Create the second-level nodes.
if(ResultSet.Tables.Count > 0)
{
// Iterate through and create a new node for each row in the query results.
// Notice that the query results are stored in the table of the DataSet.
foreach (DataRow row in ResultSet.Tables[0].Rows)
{
// Create the new node. Notice that the CategoryId is stored in the Value property
// of the node. This will make querying for items in a specific category easier when
// the third-level nodes are created.
TreeNode newNode = new TreeNode();
newNode.Text = row["CategoryName"].ToString();
newNode.Value = row["CategoryID"].ToString();
// Set the PopulateOnDemand property to true so that the child nodes can be
// dynamically populated.
newNode.PopulateOnDemand = true;
// Set additional properties for the node.
newNode.SelectAction = TreeNodeSelectAction.Expand;
// Add the new node to the ChildNodes collection of the parent node.
node.ChildNodes.Add(newNode);
}
}
}
void PopulateProducts(TreeNode node)
{
// Query for the products of the current category. These are the values
// for the third-level nodes.
DataSet ResultSet = RunQuery("Select ProductName From Products Where CategoryID=" + node.Value);
// Create the third-level nodes.
if(ResultSet.Tables.Count > 0)
{
// Iterate through and create a new node for each row in the query results.
// Notice that the query results are stored in the table of the DataSet.
foreach (DataRow row in ResultSet.Tables[0].Rows)
{
// Create the new node.
TreeNode NewNode = new TreeNode(row["ProductName"].ToString());
// Set the PopulateOnDemand property to false, because these are leaf nodes and
// do not need to be populated.
NewNode.PopulateOnDemand = false;
// Set additional properties for the node.
NewNode.SelectAction = TreeNodeSelectAction.None;
// Add the new node to the ChildNodes collection of the parent node.
node.ChildNodes.Add(NewNode);
}
}
}
DataSet RunQuery(String QueryString)
{
// Declare the connection string. This example uses Microsoft SQL Server
// and connects to the Northwind sample database.
String ConnectionString = "server=localhost;database=NorthWind;Integrated Security=SSPI";
SqlConnection DBConnection = new SqlConnection(ConnectionString);
SqlDataAdapter DBAdapter;
DataSet ResultsDataSet = new DataSet();
try
{
// Run the query and create a DataSet.
DBAdapter = new SqlDataAdapter(QueryString, DBConnection);
DBAdapter.Fill(ResultsDataSet);
// Close the database connection.
DBConnection.Close();
}
catch(Exception ex)
{
// Close the database connection if it is still open.
if(DBConnection.State == ConnectionState.Open)
{
DBConnection.Close();
}
Message.Text = "Unable to connect to the database.";
}
return ResultsDataSet;
}
</script>
<html>
<body>
<form runat="server">
<h3>TreeView PopulateNodesFromClient Example</h3>
<asp:TreeView id="LinksTreeView"
Font-Name= "Arial"
ForeColor="Blue"
EnableClientScript="true"
PopulateNodesFromClient="true"
OnTreeNodePopulate="PopulateNode"
runat="server">
<Nodes>
<asp:TreeNode Text="Inventory"
SelectAction="Expand"
PopulateOnDemand="true"/>
</Nodes>
</asp:TreeView>
<br><br>
<asp:Label id="Message" runat="server"/>
</form>
</body>
</html>
第二种方法就是使用XmlDataSource类。
html文件中:
<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="xml文件路径" XPath="xpath路径">
</asp:XmlDataSource>
cs文件中:
TreeView.DataSourceID = "XmlDataSource1";
TreeView.DataBind();
数据绑定后,就开始设置样式拉。
NodeStyle.
RootNodeStyle、ParentNodeStyle 或 LeafNodeStyle
SelectedNodeStyle.
HoverNodeStyle.
这些样式我都设置了一下,浏览一下页面,感觉还不错。
可用着用着,问题来了。发现每次选中的节点都没有变成我指定的SelectedNodeStyle样式。左找右找找不出问题来,初步发现如果是在服务器端把该节点设置成selected=true,可以看到选择样式,可我现在不想他每次点击节点的时候回发啊。怎么办呢?
我发现每个节点其实都是一个<A>标记,于是就改变主意,在绑定节点时把NavigateUrl属性设置成这样“javascript:fMenuClick()”, Target属性设为空。这样在点击这个节点的时候就是触发一个脚本函数,然后通过脚本函数来改变所点击节点的SelectedNodeStyle样式。改完后,嘿,感觉还不错,预期效果也达到了。
过了几天,页面开发得多了,老是要在各个页面之间转换,又发现了一个问题。当选中一个节点后,这个节点对应的页面已经显示完了,可是下面状态栏的进度条却还没走完,等了半天也不动。我以前遇到过这样的问题,那次是因为页面上有图片,图片没找到,才出现的。可这次我的页面根本就没有图片,也不需要下在文件。我就纳闷,这又是怎么回事呢?
然后我就一个一个的把页面上的控件,脚本去掉,看到底是什么地方影响了。找来找去,尽然是“javascript:fMenuClick()”,把这句去掉,问题就解决了。
我到网上找了半天,也没有找到原因为什么在<a>标记中把href属性设置成调用脚本会出这个问题。如果哪位高手知道原因,还请多多指教。
这个方法也行不通了,怎么办呢。又开始狂找帮助,功夫不负有心人 阿,终于找到第一次为什么没有显示选择样式了。原来HoverNodeStyle会覆盖SelectedNodeStyle的设置,于是我把HoverNodeStyle样式删掉不要,节点选择时SelectedNodeStyle样式出来了。真是太好了,不容易啊!转了一个大圈。