I have a master page which has a content section with the id cpMainContent.
I am using this master page on every webform I am creating for college project. One of such form is frmSearchPersonnel. The purpose of frmSearchPersonnel is to ask user last name of the person they want to search in a textbox and then click on search button. The ID of TextBox is
txtSearchName
Search button will do postbackUrl transfer to another form which I have named frmViewPersonnel.
In frmViewPersonnel I am trying to use following code.
NameValueCollection myRequest = Request.Form;
if(!string.IsEmptyOrNull(myRequest["txtSearchName"]))
string strSearch = myRequest["txtSearchName"];
The problem I ran into is that this didn't find any control with the name of txtSearchName. While debugging I found this in myRequest object,
[5] "ctl00$cpMainContent$txtSearchName" string
Even though when I added textbox I gave it ID of txtSearchName but when page is rendered it is adding extra string from master page.
How can I stop this? I have to use master page so don't say not to use master page :)
Why is it doing that?
Update
While Googling and Binging I found that I can use Control.ClientID in this case so looking into it.
Update 2
As suggested below to add ClientIDMode="static" in the html of control or add it in page directive. What it does is, it keeps the ID static to txtSearchName but problem is this,
<input name="ctl00$cpMainContent$txtSearchName" type="text" id="txtSearchName" />
Here name is still using ctl00 and the code I showed above,
string strSearch = myRequest["txtSearchName"]
it still won't work because nvc collection is either searchable by index or name not the id directly.
==============
You need to add a ClientIDMode="Static" to the html of the textbox:
<asp:TextBox ID="txtSearchName" runat="server" ClientIDMode="Static" />
It happens to prevent duplicate ID's. Usually it happens when you use master pages as it contains nested pages
If you want all controls with ClientIDMode="Static", you can put it in the page header of the master file.
<%# Page Language="C#" ClientIDMode="Static" %>
If you are posting to another page that uses the same master page (called SiteMaster in my case), the name of the textbox should be same the same.
string val = Request[((SiteMaster)Master).txtSearchName.UniqueID];
If you're NOT posting to a page with the same master, well, then are you using the viewstate for the textbox at all since you're posting to another page? If not, just make the control a non asp.net control:
<input type="text" name="txtSearchName"/>
If you are using viewstate and posting to another page with a different master page, well, you should use PreviousPage.
Little late here. Appreciate #aquinas and #rudeovski ze bear. Interesting and good answers.
I'd same issue and I solved it differently.
In fact, I used a public Interface.
public interface ISearch
{
string SearchText { get; }
}
Then implement ISearch interface in two aspx page say One.aspx and Two.aspx classes.
--One.aspx-- (Where I'v added TextBox1, and Button1 and set Button1.PostBackUrl="~/Two.aspx")
public partial class One : System.Web.UI.Page , ISearch
{
public string SearchText
{
get
{
return TextBox1.Text;
}
}
}
--Two.aspx--
public partial class Two : System.Web.UI.Page, ISearch
{
protected void Page_Load(object sender, EventArgs e)
{
ISearch search = (ISearch) PreviousPage;
Label1.Text = search.SearchText;
}
public string SearchText
{
get
{
throw new NotImplementedException();
}
}
}
If your try to access the input element value in code behind on post back instead of for example:
var emailAddress = Request.Form["ctl00$ctl00$ctl00$ContentContainer$MainContent$MainContent$ContentBottom$ProfileFormView$emailaddress1"];
Use
var emailAddressKeyName = Request.Form.AllKeys.FirstOrDefault(a => a.Contains("emailaddress1"));
var emailAddress = Request.Form[emailAddressKeyName];
Related
I'm trying to target the ID of an anchor within a user control named myMenu. The user control is on a master page. So, I'm trying to add a class of "active" from one of the content pages so it will highlight the link for that particular page. Right now I have:
if (Master != null)
{
var sitenav = (UserControl)Master.FindControl(id: "myMenu");
if (sitenav != null)
{
var navlink = sitenav.Parent;
}
}
I'm still trying to figure out the logic here and can't find anything that has that info. I know I'd do the htmlanchor as the type?
html in user control:
<li><a runat="server" ID="linka" href="#">Link A</a></li>
<li><a runat="server" ID="linkb" href="#">Link B</a></li>
<li><a runat="server" ID="linkc" href="#">Link C</a></li>
<li><a runat="server" ID="linkd" href="#">Link D</a></li>
MasterPage.cs:
... class MasterClass ...
public void performAction(bool toggle){
if (toggle){
myId.class += "active"; //something like that
}
}
ContentPage.cs
(MasterClass)performAction(true);
This is how you can access a master page function and get it to do something on the master page elements.
To add a css class from code behind, I'd refer you to this answer which is both elegant and complete.
Caspar Kleijne's answer
So your complete solution would be:
From within the Page you can cast the Master page to a specific type (the type of your own Master that exposes the desired functionality), using as to side step any exceptions on type mismatches:
Content Page:
var master = Master as MyMasterPage;
if (master != null)
{
master.AddClass("active");
}
In the above code, if Master is not of type MyMasterPage then master will be null and no method call will be attempted; otherwise it will be called as expected.
MasterPage
public void AddClass(string classname ){
// add a class
myMenu.CssClass = String.Join(" ", myMenu
.CssClass
.Split(' ')
.Except(new string[]{"",classname})
.Concat(new string[]{classname})
.ToArray()
);
}
I wish to create a public method on my masterpage, that I can call from within every subpage.
I am trying to wrap my head around how this should be done.
On my subpages I've made this method to fill a panel with an errormessage.
protected void errorMessage (string errorText) {
HtmlGenericControl divTag = new HtmlGenericControl("div");
Panel_Name.Controls.Add(divTag);
divTag.InnerHtml = errorText;
}
Now if I were to make this function public on my masterpage, It wont recognize my Panel as it havent been showed yet. I'm guessing the answer involves FindControl
(Sorry for my rubbish code english)
How should I do this ?
To be fair, for your scenario, I would use a UserControl (.ascx) on your Pages (.aspx).
Then, in the UserControl, have your error message markup, such as:
Code front (ErrorMessage.ascx)
<asp:Panel runat="server" ID="PanelErrorMessage" /> // creates a <div>
Code behind (ErrorMessage.ascx.cs)
public string ErrorMessage
{
get {}
set
{
PanelErrorMessage.Text = value; // sets the panel text (<div>text</div>) to value when property is set
}
}
Use your UserControl on your Page (you'll need to define this as a control tag on your page too with the prefix/suffix):
<myControls:ErrorMessage runat="server" ID="MyErrorControl" />
You can also do this in many places on your page, if you require different errors.
Then, when you have an error, you'll simply do:
MyErrorControl.ErrorMessage = "This is my error message";
Job done!
This is not really a question so I hope don't be fired!
So I have to make a twitter like timeline, a superposition of blocks containing informations.
I really don't know how to make this.. The problem is the number of blocks aren't the same each time, sometimes it will be 1 block only, sometimes two or sometimes more..
So do I make some HtmlWriter to write the html directly? I pretty new in asp.net so maybe it is possible to do that more easily! With WebUserControl maybe, a block = a wuc so I can add the number of wuc I need.. I'm quite lost so maybe somebody have done this kind of thing already and can put me on the right way..
Thank you for reading!
You are on a right track with creating a usercontrol to represent a "block", but what you're lacking is a mechanism to show them as a list.
ASP.NET has many possible solutions for this, but the simplest one would be to use a ListView control.
It's hard to provide example code without knowing what your data looks like, but let's assume you have a class called Block:
public class Block
{
public string Title {get; set;}
public string Text { get; set; }
}
To display one block, you would create a user control, let's call it BlockControl:
Markup:
<div style="margin:10px; padding:10px; background:#eee;">
<h2><%= Block.Title %></h2>
<%= Block.Text %>
</div>
Code-behind:
public partial class BlockControl : System.Web.UI.UserControl
{
//Note the public property, we'll use this to data bind the ListView's item to the user control
public Block Block { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
}
}
Then, in your .aspx page you can declare an ASP.NET ListView control, and use BlockControl in the ListView's ItemTemplate to present the data. Notice how we bind the ListView's current data item to the BlockControl.Block property.
<asp:ListView ID="BlockList" runat="server">
<ItemTemplate>
<uc:BlockControl Block="<%# Container.DataItem %>" runat="server" />
</ItemTemplate>
</asp:ListView>
From the .aspx code-behind you set the ListView data source. In your case the data probably comes from a database, but here it's just some mock data:
protected void Page_Load(object sender, EventArgs e)
{
List<Block> blocks = new List<Block>
{
new Block { Title = "Block1", Text="This is the block 1 content"},
new Block { Title = "Block2", Text="This is the block 2 content"}
};
this.BlockList.DataSource = blocks;
this.BlockList.DataBind();
}
Now you have the presentation of a single block encapsulated in a user control, and the ListView provides you with the mechanism to display a variable number of these user controls based on your data.
I need my MasterPage to be able to get ControlIDs of Controls on ContentPages, but I cannot
use <%= xxx.CLIENTID%> as it would return an error as the control(s) might not be loaded by the contentplaceholder.
Some controls have a so called BehaviourID, which is exactly what I would need as they can be directly accessed with the ID:
[Asp.net does always create unique IDs, thus modifies the ID I entered]
Unfortunately I need to access
e.g. ASP.NET Control with BehaviouraID="test"
....
document.getElementById("test")
if I were to use e.g. Label control with ID="asd"
....
document.getElementById('<%= asd.ClientID%>')
But if the Labelcontrol isn't present on the contentpage, I of course get an error on my masterpage.
I need a solution based on javascript. (server-side)
Thx :-)
You could use jQuery and access the controls via another attribute other than the ID of the control. e.g.
<asp:Label id="Label1" runat="server" bid="test" />
$('span[bid=test]')
The jQuery selector, will select the span tag with bid="test". (Label renders as span).
Best solution so far:
var HiddenButtonID = '<%= MainContent.FindControl("btnLoadGridview")!=null?
MainContent.FindControl("btnLoadGridview").ClientID:"" %>';
if (HiddenButtonID != "") {
var HiddenButton = document.getElementById(HiddenButtonID);
HiddenButton.click();
}
Where MainContent is the contentplace holder.
By http://forums.asp.net/members/sansan.aspx
You could write an json-object with all the control-ids which are present on the content-page and "register" that object in the global-scope of your page.
Some pseudo pseudo-code, because I can't test it at the moment...
void Page_Load(object sender,EventArgs e) {
System.Text.StringBuilder clientIDs = new System.Text.StringBuilder();
IEnumerator myEnumerator = Controls.GetEnumerator();
while(myEnumerator.MoveNext()) {
Control myControl = (Control) myEnumerator.Current;
clientIDs.AppendFormat("\t\"{0}\" : \"{1}\",\n", myControl.ID, myControl.ClientID);
}
page.ClientScript.RegisterStartupScript(page.GetType(),
"ClientId",
"window.ClientIDs = {" + clientIDs.ToString().Substring(0, clientIDs.ToString().Length - 2) + "};",
true);
}
It sounds like your issue is that you are using the master page for something it wasn't intended. The master page is a control just like any other control, and therefore cannot access any of the controls of its parent (the page). More info:
ASP.Net 2.0 - Master Pages: Tips, Tricks, and Traps
My suggestion is to inject the JavaScript from your page where the controls can actually be resolved. Here is a sample of how this can be done:
#Region " LoadJavaScript "
Private Sub LoadJavaScript()
Dim sb As New StringBuilder
'Build the JavaScript here...
sb.AppendFormat(" ctl = getObjectById('{0});", Me.asd.ClientID)
sb.AppendLine(" ctl.className = 'MyClass';")
'This line adds the javascript to the page including the script tags.
Page.ClientScript.RegisterClientScriptBlock(Me.GetType, "MyName", sb.ToString, True)
'Alternatively, you can add the code directly to the header, but
'you will need to add your own script tags to the StringBuilder before
'running this line. This works even if the header is in a Master Page.
'Page.Header.Controls.Add(New LiteralControl(sb.ToString))
End Sub
#End Region
I have a simple ASP.NET Web User Control. It looks like this:
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="NewsArticle.ascx.cs"
Inherits="Website.Controls.NewsArticle" %>
<div>
<asp:Literal ID="ltlBody" runat="server" />
</div>
My code behind looks like this:
namespace Website.Controls
{
public partial class NewsArticle : System.Web.UI.UserControl
{
public String bodyText
{
//get { return ltlBody.Text; }
set { ltlBody.Text = value; }
}
}
}
On a .aspx page I have <asp:Panel ID="pNews" runat="server" />
In the code behind I have:
foreach (vwNews news in newsQuery)
{
NewsArticle article = new NewsArticle();
article.bodyText = news.Body;
pNews.Controls.Add(article);
}
Every time I run this code the newsQuery is populated correctly and I get to the line
aticle.bodyText = news.Body; and then I received the error article.bodyText threw an exception of type 'System.NullReferenceException'
I am not sure what is causing this error message or how to fix it. I would think that there should not be an issue. I tried creating a constructor for my Web User Control so that it would give default values to my properties but that didn't work. Any idea how to make this work? It doesn't seem like it should be that
To load a control programatically you need to use the Page.LoadControl() method. See this MSDN article
You have a typo within the code you've written. 'aticle' instead of 'article'.