Câu hỏi Razor Nested Layouts với các phần Cascading


Tôi có một trang MVC3 sử dụng Razor làm công cụ xem của nó. Tôi muốn trang web của tôi có khả năng hiển thị. Hầu hết các skin có thể là tương tự, đủ để chúng có thể xuất phát từ layout master được chia sẻ.

Do đó, tôi đang xem xét thiết kế này:

Planned view diagram

Tuy nhiên, tôi muốn có thể gọi RenderSection trong lớp dưới cùng, _Common.cshtmlvà làm cho nó hiển thị một phần được xác định trong lớp trên cùng, Detail.cshtml. Điều này không hoạt động: RenderSection dường như chỉ hiển thị các phần được xác định lớp tiếp theo.

Tất nhiên, tôi có thể xác định từng phần trong mỗi làn da. Ví dụ, nếu _Common cần gọi RenderSection("hd") cho một phần được xác định trong Detail, Tôi chỉ đặt cái này vào mỗi cái _Skin Và nó hoạt động:

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

Điều này dẫn đến một số mã trùng lặp (vì mỗi làn da bây giờ phải có cùng một phần này) và thường cảm thấy lộn xộn. Tôi vẫn còn mới với Razor, và có vẻ như tôi có thể thiếu một cái gì đó hiển nhiên.

Khi gỡ lỗi, tôi có thể xem danh sách đầy đủ các phần được xác định trong WebViewPage.SectionWritersStack. Nếu tôi chỉ có thể nói với RenderSection xem xét toàn bộ danh sách trước khi từ bỏ, nó sẽ tìm thấy phần tôi cần. Than ôi, SectionWritersStack là không công khai.

Ngoài ra, nếu tôi có thể truy cập vào thứ bậc của các trang bố cục và cố gắng thực hiện RenderSection trong từng ngữ cảnh khác nhau, tôi có thể tìm phần tôi cần. Tôi có thể thiếu một cái gì đó, nhưng tôi không thấy bất kỳ cách nào để làm điều này.

Có cách nào để hoàn thành mục tiêu này, ngoài phương pháp mà tôi đã vạch ra?


76
2018-04-02 20:16


gốc




Các câu trả lời:


Đây là thực tế không thể ngày hôm nay bằng cách sử dụng API công cộng (ngoài việc sử dụng phương pháp định nghĩa lại phần). Bạn có thể có một số may mắn bằng cách sử dụng sự phản ánh riêng tư nhưng tất nhiên đó là một cách tiếp cận mong manh. Chúng tôi sẽ xem xét việc làm cho kịch bản này dễ dàng hơn trong phiên bản tiếp theo của Razor.

Trong thời gian chờ đợi, đây là một vài bài đăng trên blog mà tôi đã viết về chủ đề này:


35
2018-04-03 04:48



Cảm ơn bạn đã phản hồi, tôi đã chơi với các Phần lồng nhau bằng cách sử dụng cú pháp này (như trên): @section hd {@RenderSection ("hd")} ... thực sự hoạt động với tôi và có vẻ như tôi có thể sao chép các MasterPages lồng nhau hiện tại . Tôi nghĩ rằng tôi đã hiểu sai câu hỏi một chút và nghĩ rằng điều này sẽ không hoạt động. - Mark Redman
Cả câu hỏi và câu trả lời đều giúp ích rất nhiều và tôi cũng đồng ý rằng điều này sẽ dễ dàng hơn trong phiên bản tiếp theo của Razor. Và bạn cũng nên cho phép khả năng xem một phần có thể triển khai các phần cũng không được hỗ trợ tại thời điểm này. - mare
@ Shrike Tôi không nghĩ rằng bất cứ điều gì đã thay đổi trong lĩnh vực này. Bạn có thể nhập các yêu cầu tính năng trên trang web uservoice hoặc lỗi trên codeplex - marcind
@marcind Hãy nhìn vào câu trả lời của tôi. Tôi nghĩ rằng đây là những gì OP yêu cầu. Đúng? - Alireza Noori
MVC 5 đã hết. Bất kỳ bản cập nhật? Alirzea cho biết ông đã tìm ra một giải pháp, nhưng dường như nó không phù hợp với vấn đề OPs vì nó không tham khảo phần nào cả. - Snekse


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

Điều này sẽ làm công việc?


16
2017-10-15 21:37



Bạn đang sử dụng điều này trong lớp trung gian? Khá giống như lớp mở rộng này? Nếu vậy, đây là một sự thuận tiện hơn khi redeclaring một phần, hơn là giải quyết vấn đề, phải không? Chỉ cần chắc chắn rằng tôi hiểu, vì tôi đến cuối cuộc thảo luận này. - drzaus
Đối với tôi, đây là giải pháp duy nhất có hiệu quả. Nếu một phần có điều kiện được hiển thị trong bố cục cơ sở, MVC sẽ ném một lỗi thời gian chạy trừ khi phần đó là điều kiện được xác định (như thế này) trong lớp trung gian. Cảm ơn @Randy! - Michael


Tôi không chắc chắn nếu điều này là có thể trong MVC 3 nhưng trong MVC 5 tôi có thể thành công làm điều này bằng cách sử dụng thủ thuật sau đây:

Trong ~/Views/Shared/_Common.cshtml viết mã HTML phổ biến của bạn như:

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

Trong ~/Views/_ViewStart.cshtml:

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

Bây giờ tất cả những gì bạn phải làm là sử dụng _Common.cshtml như Layout cho tất cả các giao diện. Ví dụ, trong ~/Views/Shared/Skin1.cshtml:

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

<p>Something specific to Skin1</p>

@RenderBody()

Bây giờ bạn có thể thiết lập da như bố trí của bạn trong bộ điều khiển hoặc xem dựa trên tiêu chí của bạn. Ví dụ:

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

Nếu bạn chạy mã trên, bạn sẽ nhận được một trang HTML với cả nội dung của Skin1.cshtml và _Common.cshtml

Tóm lại, bạn sẽ đặt bố cục cho trang bố cục (da).


4
2017-12-29 15:13



Tôi đã có vấn đề với cách tiếp cận này bởi vì các phần sẽ không được hiển thị. Tôi tìm thấy giải pháp tại blogs.msdn.microsoft.com/marcinon/2010/12/15/… - Spikolynn


Không chắc chắn nếu điều này sẽ giúp bạn, nhưng tôi đã viết một số phương pháp mở rộng để giúp "bong bóng lên" phần từ bên trong partials, mà nên làm việc cho bố trí lồng nhau là tốt.

Đưa nội dung vào các phần cụ thể từ một khung nhìn từng phần ASP.NET MVC 3 với Công cụ Xem dao cạo

Khai báo trong bố cục / lượt xem / phần con

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

Hiển thị trong bất kỳ phụ huynh nào

@Html.RenderDelayed();

Xem liên kết câu trả lời cho nhiều trường hợp sử dụng hơn, như chỉ hiển thị một khối bị trì hoãn ngay cả khi được khai báo trong chế độ xem lặp lại, hiển thị các khối bị trì hoãn cụ thể, v.v.


1
2017-12-09 20:46