c# Accessing MasterPage elements from Child Page - c#

I've looked at several examples online and none of then seem to work for me.
All I am trying to do is access the contents of a label from the masterpage header.
Here is what i have..
A Label on the Content Page
<asp:Label ID="StaffUserName" runat="Server" />
A Label on the MasterPage called "ThisLoginName"
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">
<a runat="server" href="~/">Home</a>
</p>
</div>
<div class="float-right">
<section id="login">
Welcome! <b><asp:Label ID="ThisLoginName" runat="server" /></b>
</section>
<nav>
<ul id="menu">
<li><a runat="server" href="~/">Home</a></li>
<li><a runat="server" href="~/Admin">Admin</a></li>
</ul>
</nav>
</div>
</div>
</header>
I've read a few tutorials online but i can't seem to work this out. I do however have this at the top of my content page
<%# MasterType VirtualPath="~/Site.Master" %>
If anyone can help i'd appreciate it.

I think this is what you need.
http://www.aspdotnet-suresh.com/2012/06/access-master-page-control-from-content.html

You need to Add Public properties in Master page class:
public string LabelText
{
get { return StaffUserName.Text; } // StaffUserName is the ID of your LABEL
set { StaffUserName.Text = value; }
}
Seeing you have added: <%# MasterType VirtualPath="~/Site.Master" %> , So in your content page access this as:
Master.LabelText = "MyText";
OR
string test= Master.LabelText;

Fixed..
It was down to the fact that my code to pull the username from the windows login was running at Page load in the masterpage.
So i moved it to the
public void master_Page_PreLoad(object sender, EventArgs e)
section and then it worked.
So it must have been working all along but was pulling through an empty field.
Thanks

Related

Rendering dinamically GenericHtmlControl/Literal merged with an Asp.net Control

My Environment is: ASP.NET 4.62 / C# / Boostrap 4 framework
My application renders bootstrap 4 menu from database query.
I've a div in aspx page
<div id="myNav" runat="server"></div>
and i add code behind as
myNav.InnerHtml = mystr.ToString()
Now i need to integrate in the menu a LoginView asp.net control.
Obviously if i add
<asp:LoginView id="LoginView1" runat="server" ViewStateMode="Disabled">
as string, the browser will receive a string a not renders a control ASP.NET.
I need to render something like this
....previous items menu
<asp:LoginView id="LoginView1" runat="server" ViewStateMode="Disabled">
<AnonymousTemplate>
<ul class='nav navbar-nav ml-auto'>
<li class='nav-item'>
<a class='nav-link' href='../../Account/Login.aspx'><span class='fas fa-user'>
</span>Login</a> </li>
<li class='nav-item'><a class='nav-link' href='~/Account/Login.aspx'>
<span class='fas fa-sign-in-alt'></span> Login</a> </li> </ul>
</AnonymousTemplate>
<LoggedInTemplate>
<ul class='nav navbar-nav ml-auto'>
<li class='nav-item'>
<a class='nav-link' href='~/Account/Login.aspx'><span class='fas fa-user'></span></a>
</li>
<li class='nav-item'>
<span class="myText">Hallo, </span><a runat="server" class="username"
href="~/Account/Manage.aspx" title="Profile">
<asp:LoginName runat="server" CssClass="username" />
</a>!
<asp:LoginStatus runat="server" LogoutAction="Redirect" LogoutText="Exit"
LogoutPageUrl="~/Logout.aspx" />
</li> </ul>
</LoggedInTemplate>
</asp:LoginView>
...closing boostrap menu tag
Which is best way to resolve this type of problem ?
I need to change approach ?
You are creating the HTML at the server side; that is a possibility, but as you see, it makes it hard to combine this with ASP.NET server controls.
It would be better to put the HTML on the .aspx-page. I understand that your database knows which menu-items should be visible. And that you want to add 1 additional item, where users can login.
You could use (for example) a GridView with one column.
<Columns>
<asp:TemplateField>
<ItemTemplate>
<div>Your HTML here </div>
<div><%# Item.SomeProperty %></div>
</ItemTemplate>
</asp:TemplateField>
</Columns>
Use the data from your database to render one 'row' per menuitem in the grid. You can customize the TemplateField so it contains the bootstrap-layout as you need it.
It might also be possible to keep your current approach. I think then you should at least not create your opening and closing bootstrap-menu tags in the code-behind. You should put those tags on the .aspx-page itself, the structure would then be:
<opening tag bootstrap menu>
<div id="myNav" runat="server"></div>
<asp:LoginView id="LoginView1" runat="server" ViewStateMode="Disabled"> ... </ ..>
<closing tag bootstrap menu>

Maintain Bootstrap tab on postback from gridview sorting event C#

I'm having a little trouble getting the Bootstrap tabs to persist during a postback which occurs when sorting gridviews.
I have tried the solutions listed in Remain bootstrap tab after postback c# and http://www.aspsnippets.com/Articles/Bootstrap-Tabs-Maintain-Selected-Active-Tab-on-PostBack-in-ASPNet.aspx to no avail.
My current code is:
<div role="tabpanel" id="Tabs">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist" id="pageTabs">
<li role="presentation" class="active">Evidence Base</li>
<li role="presentation">Trials</li>
<li role="presentation">Resources</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="EvidenceBase">
<div class="col-md-12">
<asp:GridView ID="EvidenceBaseGridView" runat="server" AllowPaging="true" AllowSorting="true" OnSorting="EvidenceBaseGridView_Sorting" OnPageIndexChanging="EvidenceBaseGridView_PageIndexChanging">
</asp:GridView>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="Trials">
<div class="col-md-12">
<asp:GridView ID="TrialsGridView" runat="server" AllowPaging="true" AllowSorting="true" OnSorting="TrialsGridView_Sorting" OnPageIndexChanging="TrialsGridView_PageIndexChanging">
</asp:GridView>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="Resources">
<div class="col-md-12">
<asp:GridView ID="ResourcesGridView" runat="server" AllowPaging="true" AllowSorting="true" OnSorting="ResourcesGridView_Sorting" OnPageIndexChanging="ResourcesGridView_PageIndexChanging">
</asp:GridView>
</div>
</div>
</div>
</div>
<asp:HiddenField ID="TabName" runat="server" ClientIDMode="Static" />
And the jQuery I have used to try to set the correct tab on postback is:
<script type="text/javascript">
$('#pageTabs').on('click', 'li a', function (e) {
var addressValue = $(this).attr('href').replace("#", "");
$('#TabName').val(addressValue);
});
$(document).ready(function () {
var tab = $('#TabName').val() != "" ? $('#TabName').val() : "EvidenceBase";
$('#pageTabs a[href="' + tab + '"]').tab('show');
});
</script>
I have inspected the value of the hidden field on postback and it seems to only set to the Trials tab and the page always defaults back to the Evidence Base tab. I have also tried removing the "active" class but that makes no difference other than not displaying a tab on initial page load.
Any help on this would be greatly appreciated as my jQuery knowledge is pretty limited.
Thanks.
Do not use UpdatePanels unless its absolutely necessary. You just have to set the value of asp:HiddenField at server-side, the maintain its state after postback. Setting it clientside wont work as it will be lost on postback.
You could set it on PageIndexChanging event itself like this.
protected void EvidenceBaseGridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
//page index changing logic here
TabName.Value = "EvidenceBaseGridView";
}
You can do the same for each GridView. Also, as you re-bind the GridView after firing each event, you could set the tab name after Databind.
ASP Answer
My immediate suggestion would be to use updatepanels.
<asp:ScriptManager runat="server></asp:ScriptManager>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="EvidenceBase">
<asp:UpdatePanel runat="server">
<ContentTemplate>
<div class="col-md-12">
<asp:GridView ID="EvidenceBaseGridView" runat="server" AllowPaging="true" AllowSorting="true" OnSorting="EvidenceBaseGridView_Sorting" OnPageIndexChanging="EvidenceBaseGridView_PageIndexChanging">
</asp:GridView>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
...
This will allow the Gridviews to post back without refreshing the entire page. This means that the active class will not be re-set to the initial panel.
Note, any postbacks caused by a control outside of an UpdatePanel will refresh the entire page and thus re-set the active class on your panels.
Also note, don't forget to include your scriptmanager somewhere before your first UpdatePanel.
jQuery Answer
ASP.NET will have probably changed the ID of the hiddenfield to something like: ctl00_TabName., you may want to try $('[id*=TabName]') instead of $('#TabName') as your selector.
I find UpdatePanels useful for a backend system I've written, and use one for each bootstrap 3 tab and using the method I describe on the linked post below it works great for my website. Hopefully can help some other people too.
I have added my solution to the OP's question (not including my Updatepanels for simplicity) on the Remain bootstrap tab after postback c#
link above, which was after the OP said they tried the other answers in that post.

Get the name of the page in the content place holder of the Master Page

My Master page consists of a top bar that contains a few buttons and also a left menu bar by which the user can navigate through the web application. My Login.aspx page however is a content page but i do not want to show the left menu bar when the content page is login.
Here's a part of my Master page:
<div id="body">
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" />
<table class="auto-style1">
<tr>
<td class="auto-style2" style="vertical-align: top">
<div id="leftmenu">
<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1" StaticDisplayLevels="2" Font-Size="Medium">
<LevelSubMenuStyles>
<asp:SubMenuStyle CssClass="level1" />
</LevelSubMenuStyles>
<StaticHoverStyle CssClass="hoverstyle" />
</asp:Menu>
</div>
</td>
<td>
<asp:ContentPlaceHolder runat="server" ID="MainContent" />
<br />
</td>
</tr>
</table>
<section class="content-wrapper main-content clear-fix">
</section>
</div>
I'm looking for a way to check for the name of the opened page in my MainContent of the Master Page file and if that page is Login.aspx I would set Menu1 to hidden.
You have to think it in the opposite way: access a Master Page's control from Content Page.
This directive causes the content page's Master property to be strongly typed. Add this in you Content Page:
<%# MasterType virtualpath="~/YourMasterPage.master" %>
Create the following Property inside your Master Page:
public bool IsMenuVisible
{
get
{
return Menu1.Visible;
}
set
{
Menu1.Visible = value;
}
}
Use it inside your Content Page:
Master.IsMenuVisible = false;
More information:
Reference ASP.NET Master Page Content

How to access a tag which inside the header

I want to access a tag inside the header from the C# code.
I want to check "IF" condition and for one result disable the visibility of the tag and in other to send to another page.
the following code:
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">
<asp:ImageButton ID="ImageButton1" runat="server" ImageUrl="~\Images\AssetManagementIcon.PNG" Style="background-color: transparent; border: none;" Height="67px" Width="242px" OnClick="ImageButton1_Click" />
</p>
</div>
<div class="float-right">
<section id="login">
</section>
<nav>
<ul id="menu">
<li><a runat="server" href="~/">Log Out</a></li>
</ul>
</nav>
</div>
</div>
</header>
I want to get access to the <li><a runat="server" href="~/">Log Out</a></li>.
Looks like you're using asp.net and as you wrote you want to access the Log out tag.
I would suggest that you use the asp.net hyperlink. you could use your code as it's but you need to add an ID so you can call it in your javascript but it would be cleaner with a hyperlink like this i would recommend.
<asp:HyperLink id="hpLogout" runat="server">Log Out</asp:HyperLink>
You could also put your text inside the hyperlink control like:
<asp:HyperLink id="hpLogout" runat="server" Text="Log Out" />
but it's the same as the previous one.
You could on the other hand put your function inside your hyperlink tag like
<asp:HyperLink id="hpLogout" runat="server" Text="Log Out" OnClick="MyFunction" />
Of course MyFunction is your already defined function in c# codebehind.
and again all you need is a ID that you can call to validate with youron the codebehind for your C# code.
I hope this will help you.
Good luck.
Put an id to the '' tag. Do as following...
<header>
<ul id="menu">
<li><a id="aID" runat="server" href="~/">Log Out</a></li>
</ul>
</header>
And access it from code behind using it's id...
aID.InnerText = "hello";

Error setting Control Value within asp:ListView LayoutTemplate

So I'm really not sure what I'm doing wrong here, but my code is clearly not working. I have my list view doing everything that I need, except that when I use the ListView.FindControl() method, and then set a property on that control, it give me an Object reference not set to an instance of an object. error. Here is my code:
ASPX
<p class="rates-title"><span>
<asp:Literal ID="currentDate" runat="server"></asp:Literal></span><br>
Todays Rates</p>
<span class="rates-arrow sprite"></span>
<asp:ListView ID="RatesList" ItemPlaceholderID="RSSPlaceholder" runat="server">
<LayoutTemplate>
<ul>
<asp:PlaceHolder ID="RSSPlaceholder" runat="server"></asp:PlaceHolder>
<li>
<asp:HyperLink ID="AllRatesLink" CssClass="all-rates" runat="server">
View All Rates<span></span>
</asp:HyperLink>
</li>
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<div class="rate-text">
<p><%# Eval("Name") %></p>
<div class="rate">
<p><%# Eval("InitialRate") %>%</p>
</div>
</div>
<%# Eval("Apr") %>
<div class="todays-rates-rollover">
<p><%# Eval("ContentTruncated") %></p>
</div>
</li>
</ItemTemplate>
</asp:ListView>
Code Behind
currentDate.Text = DateTime.Now.ToString("MM.dd.yy");
HyperLink allRatesLink = (HyperLink)RatesList.FindControl("AllRatesLink");
allRatesLink.Text = "hello";
So the weird thing is that currentDate works just fine, the data that I use (elsewhere in my codebehind) works just fine for iterating through the list, but as soon as I set any property on the allRatesLink control, it gives the object reference not set error. Any ideas/help on this one?
allRatesLink is null because it is not being found which leads to the Object reference error when you try to set a property of null.
You need the FindControl to be called after the LayoutTemplate is created such as in the OnLayoutCreated handler or after DataBind()

Categories