WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

カスタム SiteMapPath

by WebSurfer 22. October 2015 19:49

各要素に LinkButton(デフォルトではハイパーリンク)を使ったカスタム SiteMapPath をユーザーコントロールとして作ってみました。

注意:
自力でユーザーコントロールを作らなくても、標準の SiteMapPath コントロールのテンプレートを使ってそれに LinkButton を実装すれば以下に紹介するユーザーコントロールと同等の機能が得られ、その方がはるかに簡単かつスマートでした。詳しくはこの記事の下の方の「2015/10/25 追記」を見てください。

SiteMapPath

SiteMapPath コントロールは、web.sitemap ファイルがきちんと書かれていれば(特に url)、それを Page に配置するだけで上の画像のようなパンくずリストが表示されます。

その個々の要素は <a title="Home" href="/default.aspx">Home</a> というようなハイパーリンクになっています。なので、これをクリックするとブラウザは /default.aspx を GET 要求しますので、単純に要求したページに遷移するだけです。

そうではなくて、クリックすると一旦表示しているページにポストバックして、HttpResponse.Redirect メソッドで /default.aspx にリダイレクトするというカスタム SiteMapPath をユーザーコントロールとして作ってみました。

その理由は、ポストバックした際にサーバー側で何らかの処置をしたいということです。

サイトのパス情報を取得するのは SiteMap オブジェクトを利用するのが便利です。SiteMap オブジェクトは ASP.NET によって自動的に生成されるサイトのナビゲーション構造のインメモリ表現で、単純に SiteMap として参照が取得できます。

それを使って、ユーザーコントロールとして、Panel に LinkButton を動的に追加していきカスタム SiteMapPath を作ってみました。コードは以下のようになります。要点はコメントとして記載しましたのでそれを見てください。

<%@ Control Language="C#" ClassName="SiteMapPathUserControl" %>

<script runat="server">

  protected void Page_Init(object sender, EventArgs e)
  {
    List<SiteMapNode> nodeList = new List<SiteMapNode>();

    // CurrentNode → RootNode の順で nodeList に Add
    CreateNodeList(SiteMap.CurrentNode, nodeList);

    // RootNode → CurrentNode の順に LinkButton を並べる
    for (int i = nodeList.Count - 1; i >= 0; i--)
    {
      if (i == 0)
      {
        // CurrentNode は LinkButton でなくLiteral
        Literal literal = new Literal();
        literal.Text = nodeList[i].Title;
        siteMapPathContainer.Controls.Add(literal);
      }
      else
      {
        // CurrentNode の親から RootNode まで LinkButton
        LinkButton button = new LinkButton();
        button.Text = nodeList[i].Title;
        button.ToolTip = nodeList[i].Description;
        button.CommandName = "navigate";
        button.CommandArgument = nodeList[i].Url;
        button.Click += new EventHandler(button_Click);
        siteMapPathContainer.Controls.Add(button);
                
        // 各要素間を " > " でつなぐ
        Literal literal = new Literal();
        literal.Text = " &gt; ";
        siteMapPathContainer.Controls.Add(literal);
      }
    }
  }

  // ルートまでたどって List<SiteMapNode> を作るヘルパ。
  // web.sitemap ですべてのノードに url が設定済みの条件。
  protected void CreateNodeList(
        SiteMapNode node, List<SiteMapNode> nodeList)
  {
    nodeList.Add(node);

    if (node.Url == SiteMap.RootNode.Url)
    {
      return;
    }
    else
    {
      CreateNodeList(node.ParentNode, nodeList);
    }
  }

  protected void button_Click(object sender, EventArgs e)
  {
    if (((LinkButton)sender).CommandName == "navigate")
    {

      // ここでリダイレクトする前に必要な処置
            
      Response.Redirect(((LinkButton)sender).CommandArgument);
    }
  }
</script>

<asp:Panel ID="siteMapPathContainer" runat="server">
</asp:Panel>

あまり需要はないかもしれませんが、せっかく作ったので忘れないように記事を書いておきました。

------ 2015/10/25 追記 ------

この記事の上の方の「注記」で書きましたように、標準 SiteMapPath コントロールのテンプレートを使ってそれに LinkButton を実装する方法が簡単でした。具体例は以下のコードの通りです。

<%@ 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 LinkButton1_Click(object sender, EventArgs e)
  {
    if (((LinkButton)sender).CommandName == "navigate")
    {
            
      // ここでリダイレクトする前に必要な処置を行う

      Response.Redirect(((LinkButton)sender).CommandArgument);
    }
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">

    <asp:SiteMapPath ID="SiteMapPath2" runat="server">
        <NodeTemplate>
            <asp:LinkButton 
                ID="LinkButton1" 
                runat="server"
                Text='<%# Eval("Title") %>'
                ToolTip='<%# Eval("Description") %>'
                CommandName="navigate" 
                CommandArgument='<%# Eval("Url") %>' 
                OnClick="LinkButton1_Click">
            </asp:LinkButton>
        </NodeTemplate>
        <CurrentNodeTemplate>
            <asp:Literal 
                ID="Literal1" 
                runat="server" Text='<%# Eval("Title") %>'>
            </asp:Literal>
        </CurrentNodeTemplate>
    </asp:SiteMapPath>

    </form>
</body>
</html>

Title, Url, Descriptin が正しく定義されている Web.sitemap ファイルがアプリケーションルート直下に存在することが条件ですので注意してください。

Tags: ,

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  April 2021  >>
MoTuWeThFrSaSu
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

View posts in large calendar