이 기사의 목적은 ASP.NET 활성화 웹 사이트의 매끄럽고 사용하기 쉬운 메뉴를 만드는 것입니다. 이를 달성하기 위해 ASP.NET 메뉴 웹 컨트롤의 표준 기능을 사용하고 계단식 스타일 시트 (CSS)를 사용하여 순전히 모양을 향상시킵니다.
CSS에 익숙한 사람들에게는이 기사의 제목이 반드시 종을 울릴 것입니다. ASP.NET 메뉴 컨트롤의 모양과 느낌을 향상시키는 데 사용되는 CSS는 "CSS의 슬라이딩 도어"라는 제목의 목록에 널리 알려진 기사에서 분류됩니다.
메뉴의 모양과 느낌을 향상시키는 데 사용되는 CSS는 목록의 기사에 철저히 설명되어 있습니다. 크레딧이 마감 될 때 크레딧. CSS를 제공해 주신 Douglas Bowman에게 감사드립니다. 익숙하지 않은 경우 먼저 그의 기사를 읽으십시오.
이 기사의 초점은 ASP.NET 환경에서 이러한 메뉴를 시뮬레이션하는 방법에 있습니다. 시작하자 ...
Visual Studio 2008을 발사하고 ASP.NET 웹 애플리케이션 프로젝트 템플릿을 사용하여 새로운 프로젝트를 만들겠습니다. 이 템플릿은 "default.aspx"라는 기본 웹 양식을 자동으로 추가합니다. 편집기에서 열고 탐색 탭에서 찾을 수있는 도구 상자에서 메뉴 컨트롤을 추가하십시오. 웹 사이트를 실행하면 빈 페이지를 쳐다 보면됩니다. 메뉴가 무엇이든 표시하려면 먼저 일부 데이터에 바인딩해야합니다.
메뉴 컨트롤의 데이터를 정의하여 방문자가 웹 사이트를 탐색 할 수 있도록하는 가장 쉬운 방법은 사이트 맵에 바인딩하는 것입니다. 제안 된 "web.sitemap"이라는 이름을 사용하여 새 사이트 맵 항목을 프로젝트에 추가하십시오. 사이트 맵은 사이트의 페이지를 계층 적으로 구성하는 XML 파일입니다. 추가 된 장점은 SitemapDatasource 컨트롤에 의해 자동으로 참조된다는 것입니다.
그런 다음 아래 목록에 표시된대로 일부 페이지를 사이트 맵에 추가하십시오.
Listing 1- Web.Sitemap
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< siteMap xmlns = " http://schemas.microsoft.com/AspNet/SiteMap-File-1.0 " >
< siteMapNode url = " " title = " " description = " " >
< siteMapNode url = " Default.aspx " title = " Home " description = " Take me back to the dasboard " />
< siteMapNode url = " Products.aspx " title = " Products " description = " Browse our catalog " />
< siteMapNode url = " Download.aspx " title = " Download " description = " Download neat stuff " />
< siteMapNode url = " Forum.aspx " title = " Forum " description = " Ask questions on our forum " />
< siteMapNode url = " Contact.aspx " title = " Contact " description = " Contact us " />
</ siteMapNode >
</ siteMap >이제 페이지에 SiteMapDatasource 컨트롤을 추가하고 메뉴 컨트롤의 DataSourceID 속성을 데이터 소스의 ID로 설정하십시오. 또한 기본값이 수직으로 기본적으로 메뉴 컨트롤의 방향 속성을 수평으로 설정하십시오. 마지막으로 SitemapDatasource의 ShowStartingNode 속성을 False로 설정하십시오. 이 작업을 수행하지 않으면 루트 노드 만 표시되며 메뉴 에이 기본 노드를 포함시키고 싶지 않습니다. 코드는 이제 Listing 2에 표시된 코드와 유사해야합니다.
Listing 2- Default.aspx
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
> </ asp:Menu >
< asp:SiteMapDataSource
ID =" SiteMapDataSource1 "
runat =" server "
ShowStartingNode =" False "
/>브라우저에서 페이지를 보면 기능하지만 지루한 메뉴가 표시됩니다.
그림 1- 일반 수평 메뉴

메뉴에 CSS를 적용하기 전에 먼저 해결해야 할 또 다른 문제가 있습니다. default.aspx 페이지를 요청할 때 생성 된 결과 HTML 코드를 살펴보면 메뉴 컨트롤이 가장 유연한 HTML 코드를 생성하지 않음을 알 수 있습니다. 기본적으로 각 메뉴 항목을 테이블에 랩합니다. 이것은 CSS를 쉽게 적용하는 데 적합하지 않습니다. 메뉴 컨트롤이 모든 메뉴 항목을 포함하는 Unorderd 목록을 생성하면 더 좋습니다.
운 좋게도 생성 된 HTML은 제어 어댑터를 사용하여 조정할 수 있습니다. 제어 어댑터를 사용하면 선호하는 HTML을 렌더링 할 수 있습니다. 고맙게도 이러한 제어 어댑터는 CodePlex에서 쉽게 사용할 수 있습니다. CSS 친화적 인 제어 어댑터 키트는 ASP.NET 메뉴 컨트롤 용을 포함하여 사전 구축 된 제어 어댑터를 제공합니다.
CSS 친화적 인 제어 어댑터를 사용하려면 다음 단계를 따릅니다.
소스 코드를 사용하고 CSSPrientsly.dll 어셈블리를 직접 컴파일해야합니다.이 기사에서 나중에 어댑터에서 사용하는 CS를 조정해야하기 때문입니다.
솔루션에 CSSPrienty 프로젝트를 추가 할 때 Visual Studio Conversion Wizard가 팝업됩니다. 변환 만 실행하면 모든 것이 순조롭게 진행되어야합니다. 전환이 완료되면 남아있는 모든 것은 ASP.NET 웹 사이트 프로젝트에서 CSSPrientsly 프로젝트에 대한 참조를 추가하는 것입니다.
웹 사이트를 실행하고 지금 생성 된 HTML 코드를 살펴보십시오.
목록 3- CSS 친화적 인 HTML 코드
< div class =" AspNet-Menu-Horizontal " id =" Menu1 " >
< ul class =" AspNet-Menu " >
< li class =" AspNet-Menu-Leaf AspNet-Menu-Selected " >
< a
href =" /Default.aspx "
class =" AspNet-Menu-Link AspNet-Menu-Selected "
title =" Take me back to the dasboard "
> Home </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a
href =" /Products.aspx "
class =" AspNet-Menu-Link "
title =" Browse our catalog "
> Products </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a
href =" /Download.aspx "
class =" AspNet-Menu-Link "
title =" Download neat stuff "
> Download </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a
href =" /Forum.aspx "
class =" AspNet-Menu-Link "
title =" Ask questions on our forum "
> Forum </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a href =" /Contact.aspx " class =" AspNet-Menu-Link " title =" Contact us "
> Contact </ a
>
</ li >
</ ul >
</ div >지금 상황이 찾고 있습니다.
비고 : CSSFrienthlyAdapters.Browser 파일을 사용하면 사용해야 할 CSS 친화적 인 제어 어댑터를 지정할 수 있습니다. 나는 내가 사용하고 싶은 어댑터를 제외한 모든 어댑터에 댓글을 달아야합니다. 이런 식으로 다른 컨트롤은 "적응"되지 않으며 기본 HTML을 계속 생성합니다.
메뉴 컨트롤의 어댑터 위 목록에 표시된 코드에서 볼 수 있듯이 <ul> , <li> 및 <a> 태그에 필요한 CSS 클래스를 자동으로 주입합니다. 이것은 우리에게 이것을 정의 해야하는 데 어려움을 덜어줍니다.
단일 페이지가 메뉴와 같은 단일 어댑터 컨트롤 이상을 포함하는 것도 일반적입니다. 각 컨트롤에 대해 뚜렷한 모양과 느낌을 원한다면 적응 된 컨트롤을 위해 CSSSelectorClass를 설정하십시오. 예를 들어 CSSSelectorClass 속성의 값을 다음과 같이 설정할 수 있습니다.
Listing 4 -CSSSelectorClass 속성
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
CssSelectorClass =" PrettyMenu "
> </ asp:Menu > 결과적으로 적응 된 컨트롤에 의해 생성 된 HTML 코드는 새로운 계층 ( <div> ) 내에 포함됩니다.
Listing 5- 생성 된 HTML 코드 포장
< div class =" PrettyMenu " id =" Menu1 " >
<!-- Other HTML code -->
</ div >이 속성은 CSS 친화적 어댑터에만 해당됩니다. 이 라이브러리에서 지원하는 컨트롤을 설정할 수있는 사용자 정의 (Expando) 속성입니다. 친절한 어댑터의 작동 방식에 대한 자세한 정보가 필요합니다. 그런 다음 다음 링크를 참조하십시오.
CSSSLECTERCLASS가 메뉴 주위에 별도의 레이어 ( <div> )를 생성하고 자동으로 주입 된 CSS 클래스를 제자리에 제자리에 놓습니다. 마침내 메뉴 스타일링을 시작할 준비가되었습니다.
사용 된 CSS는 A List Apart 기사의 CSS와 비슷합니다. 앞서 언급 한 바와 같이이 기사의 초점은 CSS의 구조에 관한 것이 아니라 깔끔한 표로 메뉴를 얻기 위해 ASP.NET 메뉴 컨트롤에 적용하는 방법에 관한 것입니다. 완성 된 결과는 그림 2에서 볼 수 있습니다.
그림 2- 완성 된 결과

다운로드 페이지 에서이 기사의 소스 코드를 찾을 수 있습니다. 스타일 시트와 필요한 이미지가 포함되어 있습니다. 완성 된 결과를 재현하려면 다음 단계 만 수행하십시오.
<Pages> 노드의 테마 속성을 기본값으로 설정하십시오. (목록 6 참조)Listing 6 -Web.config 발췌
< system .web>
<!-- ... -->
< pages theme = " Default " >
<!-- ... -->
</ pages >
<!-- ... -->
</ system .web>내 솔루션에 사용 된 CSS는 목록에있는 기사의 것과 비슷하지만 몇 가지 변경 사항이 있습니다. 주로 변화는 CSS 친화적 어댑터에 의해 적용된 CSS 구조와 관련이 있습니다.
CSS를 적용하려면 올바른 구조를 사용해야합니다. 친숙한 어댑터로 HTML을 조정하는 컨트롤을 스타일링 할 때는 백서에 언급 된 다이어그램을 사용하는 것이 편리합니다. 이 다이어그램은 CSS의 구조화 방법을 명확하게 보여줍니다.
메뉴 컨트롤의 다이어그램을 여기에서 찾을 수 있습니다.
많은 포럼에서 자주 발생한 질문 중 하나는 사용자가 최상위 메뉴에서 다른 탭을 선택할 때 변경되는 수평 서브 메뉴를 구현하는 방법입니다. 이를 만들려면 먼저 사이트 맵을 조정해야합니다.
목록 7은 조정 된 사이트 맵을 보여줍니다.
Listing 7- "하위 메뉴 항목"이있는 web.sitemap
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< siteMap xmlns = " http://schemas.microsoft.com/AspNet/SiteMap-File-1.0 " >
< siteMapNode url = " " title = " " description = " " >
< siteMapNode url = " Default.aspx " title = " Home " description = " Take me back to the dasboard " >
< siteMapNode url = " About.aspx " title = " About us " description = " " />
< siteMapNode url = " Foo.aspx " title = " Foo " description = " " />
< siteMapNode url = " Bar.aspx " title = " Bar " description = " " />
</ siteMapNode >
<!-- ... -->
</ siteMap >Brevity 's Sake Listing 7의 경우 홈 노드의 하위 메뉴 항목 (노드) 만 표시됩니다. 전체 버전에 대한 소스 코드에서 Web.Sitemap을 확인하십시오. 이제이 사이트 맵을 사용하여 웹 사이트를 탐색하면 그림 3에 표시된 효과가 표시됩니다.
그림 3- 하위 메뉴 항목

이 효과를 비활성화하려면 Listing 8에 표시된대로 메뉴 컨트롤의 MaximumDynamicDisplayLevels 속성을 0으로 설정하십시오.
Listing 8- MaximumDynamicDisplayLevels 속성
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
CssSelectorClass =" PrettyMenu "
MaximumDynamicDisplayLevels =" 0 "
> </ asp:Menu >그런 다음 두 번째 메뉴와 SiteMapDatasource 컨트롤을 추가하고 Listing 9에 표시된대로 속성을 설정하십시오.
목록 9- 하위 메뉴 컨트롤
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
CssSelectorClass =" PrettyMenu "
MaximumDynamicDisplayLevels =" 0 "
>
</ asp:Menu >
< asp:Menu
ID =" Menu2 "
runat =" server "
DataSourceID =" SitemapDataSource2 "
Orientation =" Horizontal "
CssSelectorClass =" PrettySubMenu "
>
</ asp:Menu >
< asp:SiteMapDataSource
ID =" SiteMapDataSource1 "
runat =" server "
ShowStartingNode =" False "
/>
< asp:SiteMapDataSource
ID =" SiteMapDataSource2 "
runat =" server "
StartingNodeOffset =" 1 "
ShowStartingNode =" False "
/>우리는 기본적으로 두 번째 메뉴에 사이트 맵에있는 두 번째 레벨의 노드를 표시해야하며 첫 번째 메뉴의 선택한 탭에 해당하는 시작 노드를 표시해서는 안된다고 말합니다.
또한 두 번째 메뉴의 CSSSelectorClass는 PrettySubmenu로 설정됩니다. 이 메뉴의 CSS는 첫 번째 메뉴에 대해 비슷합니다. 확인하려면 소스 코드를 다운로드하십시오. 이제 웹 사이트를 실행하면이 끔찍한 결과가 나옵니다.
그림 4- 스타일의 하위 메뉴 항목

마지막 문제 중 하나를 해결해야합니다. 이 문제를 설명하려면 프로젝트를 재구성해야합니다.
먼저 Site.master라는 프로젝트에 마스터 페이지를 추가하겠습니다. 코드, 메뉴 및 데이터 소스를 Default.aspx 페이지에서 마스터 페이지로 이동하여 본문의 첫 번째 콘텐츠 장소 홀더 바로 앞에 놓습니다. 그런 다음 Default.aspx 페이지를 안전하게 삭제할 수 있습니다.
이제 프로젝트에 몇 가지 웹 컨텐츠 양식 항목을 추가해 봅시다. 사이트 맵의 첫 번째 노드 및 하위 노드의 항목에 해당하는 웹 컨텐츠 양식을 추가하십시오.
이러한 각 웹 컨텐츠 양식의 마스터 페이지로 Site.master를 선택하십시오. Web.sitemap에 언급 된 다른 페이지는 순전히 예시적인 목적으로 있습니다.
사이트를 다시 시작하고 Foo 페이지로 이동하십시오. 이것은 문제를 드러 낼 것입니다.
그림 5- 선택 문제

사이트 맵의 하단 레벨로 탐색 했으므로 최상위 메뉴는 선택한대로 표시 해야하는 메뉴 항목을 모릅니다. 이를 해결하려면 마스터 페이지의 코드에서 코딩을해야합니다.
Listing 10은 필요한 코드를 보여줍니다.
Listing 10- 올바른 상단 레벨 메뉴 항목 선택
namespace MenuWebApplication
{
public partial class Site : System . Web . UI . MasterPage
{
private static string ExtractBaseUrl ( string url )
{
return url . Contains ( "?" ) ? url . Remove ( url . IndexOf ( '?' ) ) : url ;
}
protected void Page_Load ( object sender , EventArgs e )
{
Menu1 . DataBind ( ) ;
// Which node in the site map is currently selected?
SiteMapNode currentNode = SiteMap . CurrentNode ;
if ( currentNode != null )
{
// Obtain the Url of the currently selected node's parent node.
string parentUrl = String . Empty ;
SiteMapNode parentNode = currentNode . ParentNode ;
if ( parentNode != null )
{
parentUrl = ExtractBaseUrl ( parentNode . Url ) ;
}
// Obtain the Url of the currently selected node.
string currentUrl = ExtractBaseUrl ( currentNode . Url ) ;
// Iterate the top level menu tier.
foreach ( MenuItem menuItem in Menu1 . Items )
{
// Compare the menu item's Url against the currently
// selected node's Url or the Url of its parent.
string menuItemUrl = ExtractBaseUrl ( menuItem . NavigateUrl ) ;
if ( ( currentUrl == menuItemUrl ) || ( parentUrl == menuItemUrl ) )
{
// If either matches then mark the top level menu item as selected.
Menu1 . Items [ Menu1 . Items . IndexOf ( menuItem ) ] . Selected = true ;
break ;
}
}
}
}
}
}이제 하위 메뉴 항목을 자유롭게 선택할 수 있습니다. 해당 최상위 레벨 메뉴 항목은 방문자에게 현재 웹 사이트 내에 위치한 위치에 대한 시각적 단서를 제공합니다.
그림 6- 선택 문제 고정

컨텍스트에 민감한 수평 서브 메뉴가있는 멋진 테이블 컬 메뉴를 설정하는 것은 약간의 작업이지만 결국 매끄럽고 사용자 친화적 인 메뉴가 있습니다.
사용자 컨트롤에서 이러한 메뉴를 구현하고 해당 사용자 컨트롤을 웹 사이트 마스터 페이지에 포함시키는 것이 좋습니다. 대부분의 경우 전체 웹 사이트 전체에 해당 메뉴가 사용됩니다.