.NET TIPS

[ASP.NET]データベースからリッチなメニューを作成するには?[2.0のみ、C#、VB]

山田 祥寛
2006/03/31

 「TIPS:[ASP.NET]データベースからツリーメニューを作成するには?」でも紹介したように、.NET Frameworkではサーバ・コントロールから出来合いの機能を利用するばかりではない。ナビゲーションAPIを利用することで、例えばデータベース上のデータをTreeViewコントロールにバインドするような操作も容易に実現できる。

 そしてもちろん、ナビゲーションAPIで操作できるのはTreeViewコントロールばかりではない。代表的なナビゲーション・コントロールであるMenuコントロールでも同様の操作が可能だ。そこで本稿では、データベース上で管理されたメニュー情報からMenuコントロールを使ってよりリッチなメニューを生成する方法を紹介する。なお、本稿のサンプル・プログラムを利用するには、データベース上に前掲のTIPSでも紹介したsitemapテーブル(と中身のデータ)を用意しておく必要がある。

 それではさっそく、具体的な構築の手順をVisual Studio 2005(以降、VS 2005)環境を前提に見ていくことにしよう。

1. Menuコントロールを配置する

 最初に、フォーム・デザイナからMenuコントロールを配置する。Menuコントロールを利用するための主な操作は、Menuコントロールを配置すると(もしくは右上の三角マーク をクリックすると)表示される[Menu タスク]メニューを選択することで行えるが、ここでは[オートフォーマット]を選択し、メニューの外観だけを整えておく。いくつかデフォルトのフォーマットが用意されているが、ここでは「プロフェッショナル」を選択している。

[オートフォーマット]ダイアログ
このダイアログは、Menuコントロールの[Menu タスク]メニューから[オートフォーマット]を選択すると表示される。ここでは「プロフェッショナル」を選択している。

 「TIPS:[ASP.NET]Webフォーム上でサイト・メニュー/サイト・パスを作成するには?」のようにMenuコントロールに対してサイトマップ・ファイル(Web.sitemap)をバインドする場合には、ここで[Menu タスク]メニューの[データ ソースの選択]コンボボックスから「<新しいデータソース...>」を選択すればよい。ただし本稿ではデータベースからデータをバインドするので、ここでは特に何も行わない。

 以上で、メニューの外観にかかわる設定は完了だ。ここで参考までにVS 2005によって自動生成されたコードを引用しておく(ただし、<%--〜--%>は筆者コメント)。

<form id="form1" runat="server">
<div>
<asp:Menu ID="menu" runat="server" BackColor="#F7F6F3"
  DynamicHorizontalOffset="2" Font-Names="Verdana" Font-Size="0.8em"
  ForeColor="#7C6F57" StaticSubMenuIndent="10px">
  <%--Menuコントロールの構成要素に関するスタイルの定義--%>
  <StaticMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />
  <DynamicHoverStyle BackColor="#7C6F57" ForeColor="White" />
  <DynamicMenuStyle BackColor="#F7F6F3" />
  <StaticSelectedStyle BackColor="#5D7B9D" />
  <DynamicSelectedStyle BackColor="#5D7B9D" />
  <DynamicMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />
  <StaticHoverStyle BackColor="#7C6F57" ForeColor="White" />
</asp:Menu>
</div>
</form>
VS 2005によって自動生成されたソース・コード(C#版:menuDb_cs.aspx/VB版:menuDb_vb.aspx)の抜粋
なお本稿では、MenuコントロールのIDは「menu」とした。

2. メニューにデータを展開する

 もっとも、これだけではただのメニューの外見を定義したにすぎないので、ページがロードされたタイミングで、データベースからあらかじめ用意しておいたメニュー情報を読み込み、Menuコントロールに展開する必要がある。

 以下は、その具体的なコードだ。なお、環境によって変動する可能性があるデータベース接続文字列を個々の.aspxファイルにハード・コーディングすることは好ましくない。ここではデータベース接続文字列は、構成ファイル(Web.config)上であらかじめ定義されているものとする(接続文字列の定義に関する詳細は、別稿「VS 2005で変革されたASP.NET、Windowsフォーム、ADO.NETを総覧」の「接続文字列は構成ファイルに」をご参照いただきたい)。

using System;
using System.Data;
using System.Data.Common;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class menuDb_cs : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    this.CreateItem("-", menu.Items);
  }

  // 指定されたURL(parent)を親ノードとするノード群をメニューに追加
  private void CreateItem(String parent, MenuItemCollection items)
  {
    ConnectionStringSettings setting =
      ConfigurationManager.ConnectionStrings["db"];
    DbProviderFactory factory =
      DbProviderFactories.GetFactory(setting.ProviderName);
    using (DbConnection db = factory.CreateConnection())
    {
      db.ConnectionString = setting.ConnectionString;

      // パラメータparentをキーにsitemapテーブルを検索
      // (parentで指定されたURLを親に持つコンテンツを抽出)
      DbCommand comm = factory.CreateCommand();
      comm.CommandText =
        "SELECT url,title FROM sitemap WHERE parent=@parent";
      comm.Connection = db;
      DbParameter param = factory.CreateParameter();
      param.ParameterName = "@parent";
      param.Value = parent;
      comm.Parameters.Add(param);
      db.Open();
      DbDataReader reader = comm.ExecuteReader();

      // 取得したコンテンツを新規ノードとしてメニューに追加
      // その際、そのコンテンツが最末端でない(子ノードを持つ)
      // 場合には、CreateItemメソッドを再帰的に呼び出し、
      // 同様にノードの追加を行う
      while (reader.Read())
      {
        MenuItem item = new MenuItem();
        item.NavigateUrl = reader.GetString(0);
        item.Text = reader.GetString(1);
        this.CreateItem(reader.GetString(0), item.ChildItems);
        items.Add(item);
      }
    }
  }
}
Imports System.Data.Common

Partial Class menuDb_vb
  Inherits System.Web.UI.Page

  Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
    Me.CreateItem("-", menu.Items)
  End Sub

  ' 指定されたURL(parent)を親ノードとするノード群をメニューに追加

  Private Sub CreateItem(ByVal parent As String, ByVal items As MenuItemCollection)
    Dim setting As ConnectionStringSettings = _
        ConfigurationManager.ConnectionStrings("db")
    Dim factory As DbProviderFactory = _
        DbProviderFactories.GetFactory(setting.ProviderName)
    Using db As DbConnection = factory.CreateConnection()
      db.ConnectionString = setting.ConnectionString

      ' パラメータparentをキーにsitemapテーブルを検索
      ' (parentで指定されたURLを親に持つコンテンツを抽出)
      Dim comm As DbCommand = factory.CreateCommand()
      comm.CommandText = _
        "SELECT url,title FROM sitemap WHERE parent=@parent"
      comm.Connection = db
      Dim param As DbParameter = factory.CreateParameter()
      param.ParameterName = "@parent"
      param.Value = parent
      comm.Parameters.Add(param)
      db.Open()
      Dim reader As DbDataReader = comm.ExecuteReader()

      ' 取得したコンテンツを新規ノードとしてメニューに追加
      ' その際、そのコンテンツが最末端でない(子ノードを持つ)
      ' 場合には、CreateItemメソッドを再帰的に呼び出し、
      ' 同様にノードの追加を行う
      Do While reader.Read()
        Dim item As New MenuItem ()
        item.NavigateUrl = reader.GetString(0)
        item.Text = reader.GetString(1)
        Me.CreateItem(reader.GetString(0), item.ChildItems)
        items.Add(item)
      Loop
    End Using
  End Sub
End Class
データベースから動的にメニューを生成するWebフォーム(上:menu_db_cs.aspx/下:menu_db_vb.aspx)

 コードの構造は、「TIPS:[ASP.NET]データベースからツリーメニューを作成するには?」とほとんど同様だ(併せて参考にしていただきたい)。
 CreateItemメソッドの第2パラメータに指定されたMenuItemCollectionオブジェクト(Microsoft.Web.UI.WebControls名前空間)に対してAddメソッドを呼び出すことで、メニュー項目を順に追加していく。もしも該当する項目に下位のノードが存在する場合には、CreateItemメソッドは再帰的に呼び出され、最下位のノードまでが順に処理されるというわけだ。

 以上を理解したら、さっそく、サンプル・プログラムを実行してみよう。

サンプル・プログラム(menuDb_cs.aspx/menuDb_vb.aspx)の実行結果

 データベースに格納した内容に従って、以下のような結果を得られれば成功だ。End of Article

利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:Webフォーム 処理対象:ナビゲーション
使用ライブラリ:Menuコントロール(Microsoft.Web.UI.WebControls名前空間)
使用ライブラリ:MenuItemCollectionクラス(Microsoft.Web.UI.WebControls名前空間)
関連TIPS:[ASP.NET]データベースからツリーメニューを作成するには?
関連TIPS:[ASP.NET]Webフォーム上でサイト・メニュー/サイト・パスを作成するには?

この記事と関連性の高い別の.NET TIPS
[ASP.NET]データベースからツリー・メニューを作成するには?
[ASP.NET]TreeViewコントロールで深階層のツリー情報を効率よく読み込むには?
[ASP.NET]Webフォーム上でサイト・メニュー/サイト・パスを作成するには?
[ASP.NET]GridViewコントロールでデータソースの内容を表示するには?
[ASP.NET]データベースからツリー・メニューを生成するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間