계단식 섹션이있는 Razor 중첩 레이아웃


80

Razor를 뷰 엔진으로 사용하는 MVC3 사이트가 있습니다. 내 사이트를 스키닝 ​​할 수 있기를 원합니다. 가능한 대부분의 스킨은 공유 마스터 레이아웃에서 파생 될 수있을 정도로 유사합니다.

따라서이 디자인을 고려하고 있습니다.

계획된보기 다이어그램

그러나 RenderSection맨 아래 레이어에서을 호출 _Common.cshtml하고 맨 위 레이어에 정의 된 섹션을 렌더링하도록하고 싶습니다 Detail.cshtml. 이것은 작동하지 않습니다. RenderSection분명히 다음 레이어에 정의 된 섹션 만 렌더링합니다.

물론 각 스킨의 각 섹션을 정의 할 수 있습니다. 예를 들어에 정의 된 섹션 _Common을 호출해야하는 경우 각 RenderSection("hd")섹션에 Detail배치하면 다음 _Skin과 같이 작동합니다.

@section hd {
    @RenderSection("hd")
}

이로 인해 코드가 일부 중복되고 (이제 각 스킨에 동일한 섹션이 있어야하므로) 일반적으로 지저분하게 느껴집니다. 나는 아직 Razor를 처음 사용하고 있으며 분명한 것을 놓친 것 같습니다.

디버깅 할 때 WebViewPage.SectionWritersStack에서 정의 된 섹션의 전체 목록을 볼 수 있습니다. 포기하기 전에 전체 목록을 살펴 보도록 RenderSection에 지시 할 수 있다면 필요한 섹션을 찾을 수 있습니다. 아아, SectionWritersStack은 비공개입니다.

또는 레이아웃 페이지의 계층 구조에 액세스하고 서로 다른 컨텍스트에서 RenderSection 실행을 시도 할 수 있다면 필요한 섹션을 찾을 수 있습니다. 나는 아마도 뭔가를 놓치고 있지만 이것을 할 방법이 없다고 생각합니다.

이미 설명한 방법 외에이 목표를 달성 할 수있는 방법이 있습니까?

답변:


35

이것은 실제로 공개 API를 사용하여 가능하지 않습니다 (섹션 재정의 접근 방식을 사용하는 경우 제외). 사적인 성찰을 사용하면 운이 좋을 수도 있지만 당연히 깨지기 쉬운 접근 방식입니다. 다음 버전의 Razor에서이 시나리오를 더 쉽게 만드는 방법을 살펴 보겠습니다.

그 동안 내가 주제에 대해 작성한 몇 가지 블로그 게시물이 있습니다.


3
응답 해 주셔서 감사합니다.이 구문 (위와 같이)을 사용하여 중첩 된 섹션을 가지고 놀았습니다. @section hd {@RenderSection ( "hd")} ... 실제로 저를 위해 작동하고 기존 중첩 된 MasterPages를 복제 할 수있는 것처럼 보입니다. . 나는 질문을 약간 오해하고 이것이 효과가 없을 것이라고 생각했다고 생각합니다.
Mark Redman 2011 년

2
질문과 답변 모두 많은 도움이되었으며 다음 버전의 Razor에서이 작업이 더 쉬워 져야한다는 데 동의합니다. 또한 부분보기가 현재 지원되지 않는 섹션도 구현할 수있는 가능성을 활성화해야합니다.
mare

1
@Shrike 나는이 영역에서 아무것도 변경되지 않았다고 생각합니다. uservoice 사이트 에 기능 요청을 입력 하거나 codeplex에
marcind

1
@marcind 내 대답을 살펴보십시오. 나는 이것이 OP가 요구 한 것이라고 생각합니다. 권리?
Alireza Noori

1
MVC 5가 나왔습니다. 모든 업데이트? Alirzea는 해결책을 찾았지만 섹션을 전혀 참조하지 않았기 때문에 OP 문제와 일치하지 않는 것 같습니다.
Snekse

17
@helper ForwardSection( string section )
{
   if (IsSectionDefined(section))
   {
       DefineSection(section, () => Write(RenderSection(section)));
   }
}

이것이 일을할까요?


중간 레이어에서 이것을 사용하고 있습니까? 이 확장 클래스 와 거의 동일 합니까? 그렇다면 문제를 해결하는 것보다 섹션을 재 선언 할 때 더 편리합니다. 이 토론에 늦었 기 때문에 이해했는지 확인하십시오.
drzaus

저에게는 이것이 효과가 있었던 유일한 솔루션이었습니다. 섹션이 기본 레이아웃에서 조건부로 렌더링되는 경우 해당 섹션이 중간 레이어에서 조건부로 정의 되지 않는 한 MVC에서 런타임 오류가 발생 합니다. 감사합니다 @ 랜디!
Michael

현재 정의 된 모든 섹션을 전달할 수 있습니까?
nvirth

4

MVC 3에서 이것이 가능한지 확실하지 않지만 MVC 5에서는 다음 트릭을 사용하여 성공적으로 수행 할 수 있습니다.

다음 ~/Views/Shared/_Common.cshtml과 같은 일반적인 HTML 코드를 작성하십시오.

<!DOCTYPE html>
<html lang="fa">
<head>
    <title>Skinnable - @ViewBag.Title</title>
</head>
<body>
@RenderBody()
</body>
</html>

에서 ~/Views/_ViewStart.cshtml:

@{
    Layout = "~/Views/Shared/_Common.cshtml";
}

이제 당신이해야 할 사용하는 것입니다 _Common.cshtml은 AS를 Layout모든 스킨. 예를 들어 ~/Views/Shared/Skin1.cshtml:

@{
    Layout = "~/Views/Shared/_Common.cshtml";
}

<p>Something specific to Skin1</p>

@RenderBody()

이제 컨트롤러에서 스킨을 레이아웃으로 설정하거나 기준에 따라 볼 수 있습니다. 예를 들면 :

    public ActionResult Index()
    {
        //....
        if (user.SelectedSkin == Skins.Skin1)
            return View("ViewName", "Skin1", model);
    }

위의 코드를 실행하면 내용 Skin1.cshtml과 내용이 모두 포함 된 HTML 페이지가 표시됩니다._Common.cshtml

간단히 말해 (스킨) 레이아웃 페이지의 레이아웃을 설정합니다.


섹션이 보이지 않기 때문에이 접근 방식에 문제가있었습니다. blogs.msdn.microsoft.com/marcinon/2010/12/15/…
Spikolynn

1

이것이 도움이 될지는 확실하지 않지만, 부분 내에서 섹션을 "버블 업"하는 데 도움이되는 몇 가지 확장 메서드를 작성했습니다. 이는 중첩 된 레이아웃에서도 작동합니다.

Razor View Engine을 사용하여 부분보기 ASP.NET MVC 3에서 특정 섹션에 콘텐츠 삽입

자식 레이아웃 /보기 / 일부 선언

@using (Html.Delayed()) {
    <b>show me multiple times, @Model.Whatever</b>
}

모든 부모에서 렌더링

@Html.RenderDelayed();

반복되는 뷰에서 선언 된 경우에도 하나의 지연된 블록 만 렌더링하거나 특정 지연된 블록을 렌더링하는 등 더 많은 사용 사례에 대해서는 답변 링크를 참조하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.