Build a user control with placeholder like a master page in .NET
If you want to run through this walkthrough, please follow the guide on setting up our test environment.
Experience Level - Intermediate
Reusable code
On our user controls we regularly re-use the same parts of HTML again and again. We found the answer on Stack Overflow after a lengthy search, so as usual popped our solution on here.
Where there is a need for completely reusable code, we tend to split things out into control parts, for instance on Ousia Light, we reuse the folder control on many other controls as it has it's own code to display the code from the URL. These are easy to use as they can be dragged into the other control and the binding works, however, we also have quite meaty outer parts that open and close either side of the block we are building, for example the pop-up control we are going to build in this article.
First step if you are following on the academy test environment is to add a User Control called PopUp.ascx to the Controls folder and add the HTML as below.
HTML
<div class="hPop" style="opacity: 0;" id="oPop" runat="server"> <div class="xPop"> <div class="oPopCont"> <div class="oPopData clearfix"> <div class="oPopHead" id="oPopHead"><span class="oPopTitle" id="oPopTitle" runat="server">User</span><span class="close" onclick="ousPopHide(document.getElementById('<%=oPop.ClientID%>'))">X</span></div> <div class="oPopBody clearfix" id="oPopBody"> <asp:Placeholder runat="server" ID="phContent"/> </div> </div> </div> </div></div>
Add the code behind
Next step is to go into the code behind, by right clicking on the new user control in the Solution Explorer or on the designer and selecting "View Code", here we will add some binding to insert the code on initialisation.
VB.NET
<ParseChildren(True, "Content")><PersistChildren(False)>Partial Class PopUp 'Don't overwrite this if you aren't following via the academy! Inherits System.Web.UI.UserControl Public PopID As String Public PopTitle As String Public Property _content As Control <PersistenceMode(PersistenceMode.InnerProperty)> Public Property Content As Control Get Return _content End Get Set(ByVal value As Control) _content = value End Set End Property Protected Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init phContent.Controls.Add(CType(_content, Control)) PopID = oPop.ClientID oPopTitle.InnerText = PopTitle End SubEnd Class
C#
[ParseChildren(true, "Content")][PersistChildren(false)]partial class PopUp : System.Web.UI.UserControl// Don't overwrite this if you aren't following via the academy!{ public string PopID; public string PopTitle; public Control _content { get; set; } [PersistenceMode(PersistenceMode.InnerProperty)] public Control Content { get { return _content; } set { _content = value; } } protected void Page_Init(object sender, EventArgs e) { phContent.Controls.Add((Control)_content); PopID = oPop.ClientID; oPopTitle.InnerText = PopTitle; }}
Add a page
Now that we've done the control, we can drag it into any new page, so add a page called PopUp to your solution, in the pages section if using the academy.
The content of the page below the page initialisation should match what we have below. The majority is styling and a couple of scripts for the popup.
<%@ Register Src="~/Controls/PopUp.ascx" TagPrefix="uc1" TagName="PopUp" %><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"><title></title><style>.button{ position: fixed; left: 50%; margin-left: -5%; width: 10%; top: 50%; margin-top: -20px; height: 40px; display: block; border-radius: 10px; text-align: center; line-height: 40px; background-color: mediumpurple;}.dataarea{background-color:white;min-height:75vh;}.hPop { display: none; -webkit-transition: opacity 400ms linear; -moz-transition: opacity 400ms linear; transition: opacity 400ms linear;}.oPop { display: block; -webkit-transition: opacity 400ms linear; -moz-transition: opacity 400ms linear; transition: opacity 400ms linear; position: fixed; top: 0px; left: 0px; height: 100vh; width: 100vw; display: block; z-index:999;}.xPop { display: table; z-index: 999999; padding: 0% 0%; position: fixed; background-color: #000; top: 0px; left: 0px; width: 100%; height: 100%; background: rgba(0,0,0,0.75);}.oPopCont { display: table-cell; position: relative; vertical-align: middle; text-align: center; padding: 5%;}.oPopData { display: block; position: relative; background-color: #eee; margin: auto; overflow-x: auto; border-radius: 16px; -webkit-box-shadow: 0px 4px 20px 0px rgb(0 0 0 / 50%); -moz-box-shadow: 0px 4px 20px 0px rgb(0 0 0 / 50%); box-shadow: 0px 4px 20px 0px rgb(0 0 0 / 50%);}.oPopHead { display: block; position: sticky; font-size: 18px; line-height: 40px; top: 0px; background-color: inherit; z-index: 999; background-color: #ddd; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; -o-user-select: none;}.oPopTitle { font-size: 16px; font-weight: bold; user-select: none; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; -o-user-select: none;}.oPopHead i { position: absolute; display: block; height: 40px; width: 40px; top: 0px; right: 0px; background-color: #ccc;}.oPopHead .close { position: absolute; display: block; height: 40px; width: 40px; top: 0px; right: 0px; background-color: #ccc;}.oPopBody { display: block; position: relative; padding: 1%; max-height: 80vh; overflow-x: auto;}</style><script>function disableScroll() { scrollTop = window.pageYOffset || document.documentElement.scrollTop; scrollLeft = window.pageXOffset || document.documentElement.scrollLeft, window.onscroll = function () { window.scrollTo(scrollLeft, scrollTop); };}function enableScroll() { window.onscroll = function () { };}function ousPopShow(el) { if (el !== undefined) { disableScroll(); el.className = 'oPop'; window.setTimeout(function () { el.style.opacity = 1; }, 0); //alert(document.scrollX); }}function ousPopHide(el) { if (el !== undefined) { el.style.opacity = 0; window.setTimeout(function () { el.className = 'hPop'; }, 400); enableScroll(); }}</script></head><body> <form id="form1" runat="server"> <div> <uc1:PopUp runat="server" id="PopUp" PopTitle="Academy"> <div class="dataarea"> Your Content Goes Here </div> </uc1:PopUp> <a onclick="ousPopShow(document.getElementById('<%=PopUp.PopID%>'));" class="button">Click</a> </div> </form></body></html>
Quick note
<uc1:PopUp runat="server" id="PopUp" PopTitle="Academy"/>
to
<uc1:PopUp runat="server" id="PopUp" PopTitle="Academy"/></uc1:PopUp>
This will allow you to work with the code just as if it were a master page. We are working on removing the warnings, and will add the work around if we find it.