通常、メニューの各レベルには、それに関連付けられた異なるループが必要です。たとえば、最初のレベル (例: ホーム、製品、about_us) は上部に水平に表示され、2 番目のレベルは関連する親メニュー項目の下のドロップダウンに表示されます。 、第 2 レベルのメニュー項目の下に第 3 レベルが表示されます。
したがって、ループについては、理論的にはレベルごとに分割したくありませんが、親メニュー項目へのリンクを維持して表示できるようにします。もう 1 つのより一般的なことは、ツリーの最上位のメニューが他のメニュー項目のコンテナー要素として無視されることが多いことです。これにより、次のような複数のトップレベル メニューを使用できます。
編集: コードを修正しました..編集履歴を元に戻して、私がいかに天才ではないかを確認してください:p
string html;
int lastLevel = 0;
void placeMenu( Menu menu, int level)
{
// if level hasn't changed close last menu-item
if( lastLevel == level ) html += "</li>";
// if we're deeper, open a new <UL>
else if( lastLevel < level ) html += "<ul>";
// if we're less deep, close the last <UL> and it's parent menu-item
else if( lastLevel > level ) html += "</ul></li>";
// add current menu item without closing it's <LI> so the next itteration of the loop can add a submenu if needed
html += "<li><a href='http://link/to/page'>" + menu.Name + "</a>";
lastLevel = level;
}
void setupMenu( Menu menu, int level )
{
foreach( var currentMenu in menu._ChildMenus )
{
// place current menu
placeMenu( currentMenu, level + 1 );
// place submenus
setupMenu( currentMenu, level + 1 );
}
}
string setupWholeMenu( Menu menu )
{
setupMenu( menu, 0 );
// close any elements left open by the recursive loop
html = html + "</li></ul>";
return html;
}
このコードは、メニュー構造から通常の html の順序付けされていないレベルのリストを作成するように設計されています。これは、HTML でメニューを追加してスタイルを設定する標準的な方法です。ここで HTML 順不同リストを使用する理由は、正しく実装されていれば、Javascript と CSS が無効になっていても (GSM と弱視者向けのスクリーン リーダー)、このリスト構造が引き続き表示され、Javascript が無効になっていてもすべての IE6+ で機能するためです。
正直に言うと、MVC では通常、HTML の順序付けられていないリストとして宣言的な方法でメニューを直接設定するだけで簡単に割り当てられます。部分的な共有ページに配置するか、定義することでどこにでも表示すると、複数の方法でスタイルを設定できます。あなたのレイアウトページでそれを。このアプローチは、上記のように動的なメニュー構造がある場合でも機能しますが、Razor を使用してリストを作成する方がおそらく簡単です。
もう 1 つの注意点は、この種の再帰関数では、文字列を連結するよりもはるかに効率的なStringBuilderを使用する必要があることです。ただし、メニュー構造 (それぞれが 2 ~ 3 の連結で構築された最大 30 個の項目を含む) の場合、これによって顕著な遅延が発生することはありません。将来のために留意する必要があります。