Abs
Abs

Reputation: 165

Render html content in layout based on value defined in consuming page

Is there a way in which I can define a value or section in an MVC page that is consumed by the Layout file to display optional content in the layout file.

_Layout.cshtml

@if (someValueToCheck)
{
    //HTML content that will render on every page requiring this content
}

Somepage.cshtml

@{
   // set someValueToCheck to notify the Layout to render content
}

Upvotes: 1

Views: 484

Answers (2)

Erik Philips
Erik Philips

Reputation: 54628

Sections are typically used to define content in a page, and displayed in a Layout. So if that's what you're actually trying to accomplish then it would look like:

_Layout.cshtml

@if(IsSectionDefined("optionalSection")){
  <div class="optional-content">
       @RenderSection(commonBodyContainer)
  </div>    
} 

@RenderBody()

renderOptionalContent.cshtml

@section optionalSection 
{ 
  <div>Content for opional-content</div>
}

If you don't need to render content passed from the view to the layout, I prefer to create a strongly typed, descriptive method to do the logic and store the value in the ViewData:

internal static class WebViewPageExtensions
{
    const string ViewDataContentBlahKey = "ContentBlahKey";

    public static void SetShowContentBlah(this WebViewPage instance
       ,bool value)
    {
      instance.ViewData[ViewDataContentBlahKey] = value;
    }

    public static void GetShowContentBlah(this WebViewPage instance)
    {
      // if it's not set to false, it will be null
      var result = instance.ViewData[ViewDataContentBlahKey] as bool?;
      return result.HasValue && result.Value;
    }
}

_Layout.cshtml

@if(GetShowContentBlah())){
  <div class="optional-content">
    My Optional Content
  </div>    
} 

renderOptionalContent.cshtml

@{ SetShowContentBlah(true); }

Upvotes: 0

Abs
Abs

Reputation: 165

I think this can't be done and the closest is defining an almost identical layout file, but that is still ugly, therefore the below may be better:

_Layout2.cshtml

@RenderPage("_Layout")

<div class="common-body-container">
    <div class="common-body-container-header">
        <div class="common-body-container-page-title">blah blah!</div>
    </div>
    <div class="common-body-container-contents">
        @RenderBody()
    </div>
</div>

This way I am not redifining an almost identical layout file and also not repeating the HTML tags forming the container on evey page.

Edit: Thanks to @ErikPhilips IsSectionDefined(string section) Does the trick, it will render optional content from within the layout only when a section is defined within the content page:

_Layout.cshtml

@if(IsSectionDefined("commonBodyContainer")){
    <div class="common-body-container">
       <div class="common-body-container-header">
           <div class="common-body-container-page-title">blah blah!</div>
       </div>
       <div class="common-body-container-contents">
           @RenderSection(commonBodyContainer)
       </div>
    </div>    
} else {
    @RenderBody()
}

Upvotes: 1

Related Questions