by WebSurfer
2011年11月13日 19:12
TreeView のノードをクリックするとポストバックが起こり、サーバー側で TreeView.SelectedNode プロパティでクリックされた TreeNode を取得できます。
上の画像は、book というノードをクリックし、book ノードに含まれる子ノードの内 title ノードを取得してその Value を表示したものです。
そのコードは下に示したサンプルのとおりです。データとして使用している XML ファイルは MSDN ライブラリの チュートリアル : TreeView コントロールでの階層データの表示 のものです。
しかしながら、このコードでは、どの book ノードをクリックしても、表示されるのは一番上の book ノード下の title ノードの Value になってしまいます。
何故でしょう? 理由は以下の通りです。
どのノードがクリックされたかのサーバー側での判定は、root からクリックされたノードまでの Value をつなげた文字列を javascript:__doPostBack 関数の引数に設定し、ポストバックされた際にそれを取得して識別しています。
下のサンプルコードの例では、book ノードのハイパーリンクとして a 要素の href 属性に以下のように設定されます。
href="javascript:__doPostBack('TreeView1','sbookstore\\genre\\book')"
book ノードの Value はどれも同じ book ですので、__doPostBack 関数の引数はどの book ノードでも同じになってしまいます。それゆえサーバー側ではどの book がクリックされたか特定できません。だから、最初に該当する一番上の book が選択されたと判定してしまうようです。
解決策は、book ノードの Value が一意になるように TreeView の DataBindings に以下のように設定してやることです。
<asp:TreeNodeBinding DataMember="book"
TextField="#Name"
ValueField="ISBN" />
考えてみれば、Windows アプリとは違って、ブラウザの画面に表示されているノードはインスタンスを指していないので、当たり前ですね。
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void TreeView1_SelectedNodeChanged(
object sender, EventArgs e)
{
TreeNode selectedNode = TreeView1.SelectedNode;
if (selectedNode.Text == "book")
{
foreach (TreeNode child in selectedNode.ChildNodes)
{
if (child.Text == "title")
{
Label1.Text =
"選択した本のタイトル: " + child.Value;
break;
}
}
}
else
{
Label1.Text = String.Empty;
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TreeView ID="TreeView1"
runat="server"
DataSourceID="XmlDataSource1"
OnSelectedNodeChanged="TreeView1_SelectedNodeChanged">
<DataBindings>
<asp:TreeNodeBinding DataMember="title"
TextField="#Name"
ValueField="#InnerText" />
</DataBindings>
</asp:TreeView>
<asp:XmlDataSource ID="XmlDataSource1"
runat="server"
DataFile="~/App_Data/Bookstore.xml">
</asp:XmlDataSource>
<br />
<br />
<asp:Label ID="Label1" runat="server">
</asp:Label>
</div>
</form>
</body>
</html>