Passing Data from User Control in Master Page(s) to Content Page - asp.net

I've looked at several similar questions to this one and right now I am trying to use the FindControl method without success.
My Web Forms application has several master pages. Common to all master pages is a search box and button in a nav user control at the top. I'm trying to grab the search term entered on the SearchResults page:
HtmlGenericControl topNavDiv = (HtmlGenericControl)Master.FindControl("topNavDiv");
Control topNav = (UserControl)Page.FindControl("topNav");
if (topNav != null)
{
TextBox searchBox = topNav.FindControl("searchBox") as TextBox;
if (searchBox != null)
{
Response.Write(searchBox.Text.Trim());
}
else
{
resultsPanel.Visible = false;
messagePanel.Visible = true;
}
}
In the first line, the topNavDiv variable is null. I was considering accessing the user control via a master page property, but with several different master pages I don't know how to determine the id of the master page as the search could be initiated from anywhere in the site...
UPDATE:
I was able to grab the topNav div, searchBox textbox as follows:
Control topNav = (UserControl)Master.FindControl("topNav");
if (topNav != null)
{
TextBox searchBox = topNav.FindControl("searchBox") as TextBox;
if (!String.IsNullOrEmpty(searchBox.Text))
{
Response.Write(searchBox.Text.Trim());
}
else
{
resultsPanel.Visible = false;
messagePanel.Visible = true;
}
}
The only problem is that the search box text entered is not being persisted.

If you need to keep the data out of the query string for some reason you could use a Property on your MasterPage.cs file.
public string SearchTerm
{
get
{
return searchBox.Text;
}
}
Then you can use that wherever you need to like this:
MasterPage master = (MasterPage)this.Master;
master.SearchTerm;

Since this is an Intranet site, I was able to utilize a query string parameter to obtain the search term as follows:
Nav with Search Box User Control:
<ul class="navbar-form navbar-left">
<li>
<asp:TextBox ID="searchBox" class="form-control col-lg-8"
placeholder="Search" runat="server"></asp:TextBox>
<asp:Button ID="searchButton" CssClass="btn btn-warning" Text="Search"
runat="server" OnClick="searchButton_Click" />
</li>
</ul>
User Control Code-Behind:
protected void searchButton_Click(object sender, EventArgs e)
{
Response.Redirect("~/Search/SearchResults.aspx?term="+searchBox.Text.Trim());
}
Search Results Page Code-Behind:
if (!Page.IsPostBack)
{
if (!String.IsNullOrEmpty(Request.QueryString["term"]))
{
term = Request.QueryString["term"].ToString();
Response.Write(term);
}
else
{
resultsPanel.Visible = false;
messagePanel.Visible = true;
}
}
What I would really like to know is if it is programmatically possible to determine in a page's code-behind, the identity of the master page of the requesting page?

Related

Why binding event is not called after submit button clicked for user control (added code)

I have a web page that uses single user control and a asp:repeater that uses the same user control and both are created in Page_Load. Both bahave differently in a submit button clicking event. The binding event for each of the repeater (depdentBasicInfo)'s user control is called after submit button clicking before page_load. But the binding event is not for the single user control (spouseBasicInfo). Why? Also the user control create a runtime control (assuming a TextBox). I found there is no way to retrieve the runtime control's Text property after clicking the submit as the control becomes null after PostBack. How to retrieve the property easily? Could any one help me? Thanks.
<!--USER CONTROL -->
<asp:Panel runat="server" ID="PnlSpouseInformation" Visible="true">
<h3 id="ApplicantLabel" runat="server"></h3>
<div class="dependentInformation">
<asp:PlaceHolder ID="phDependentInformation" runat="server"></asp:PlaceHolder>
</div>
</asp:Panel>
<!-- code behind -->
public partial class userInfo : System.Web.UI.UserControl
{
public string identity;
public string applicantTitle
{
set { ApplicantLabel.InnerText = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
public void Bind()
{
WebControl textBox = new TextBox
{
Text = identity,
ID = "textbox"
};
phDependentInformation.Controls.Add(textBox);
}
}
<html>
<head runat="server">
<title>Test user control binding</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:userInfo runat="server" ID="SpouseBasicInfo" Visible="false" />
<asp:Repeater runat="server" ID="RptDependents" OnItemCreated="RptDependents_ItemCreated">
<ItemTemplate>
<uc1:userInfo runat="server" ID="DependentBasicInfo" />
</ItemTemplate>
</asp:Repeater>
<asp:LinkButton runat="server" ID="submit" OnClick="OnClickSubmit"><span>Submit</span></asp:LinkButton>
</div>
</form>
</body>
public partial class _default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
SpouseBasicInfo.identity = "spouse";
SpouseBasicInfo.Bind();
SpouseBasicInfo.Visible = true;
List<String> list = new List<string>();
list.Add("Dependent A");
list.Add("Dependent B");
RptDependents.DataSource = list;
RptDependents.DataBind();
}
}
protected void OnClickSubmit(object sender, EventArgs e)
{
if (!Page.IsValid)
{
return;
}
var textbox = SpouseBasicInfo.FindControl("textbox") as TextBox;
string spouseName = textbox.Text;
}
protected void RptDependents_ItemCreated(object sender, RepeaterItemEventArgs e)
{
switch (e.Item.ItemType)
{
case ListItemType.Item:
case ListItemType.AlternatingItem:
{
var dependentInfo = e.Item.DataItem as String;
var dependentBasicInfo = e.Item.FindControl("DependentBasicInfo") as userInfo;
if (dependentBasicInfo == null) return;
dependentBasicInfo.applicantTitle = "Dependent " + (e.Item.ItemIndex + 1);
dependentBasicInfo.identity = dependentInfo;
dependentBasicInfo.Bind();
}
break;
}
}
}
</html>
Can you please post your code so we can get a look at it? Also, you say the runtime control becomes null after post back. Is the text property of the control set after the page is rendered? if so you may be able to use a hidden asp label on the page that can hold the text property. When the page is posted back the hidden label still holds the last value held for the text property of said control.
"User control (spouseBasicInfo). Why? Also the user control create a runtime control (assuming a TextBox). I found there is no way to retrieve the runtime control's Text property after clicking the submit as the control becomes null after PostBack. How to retrieve the property easily? Could any one help me? Thanks."
I haven't been working with asp.net for a long time so I don't think I can answer all the questions you are asking. But, if you are creating a text box at runtime and using the placeholder to deliver the object to the screen then yes, the textbox control will be null after post back. This is because it is not an asp.control like a textbox or label that is not runtime created. You can retrieve the value previously held in the text box by creating a label on screen that is hidden. Place your value in the hidden label and the runtime created text box. After post back the hidden label will still hold the value previous to post back and you can retrieve as you would normally retrieve a value held in a control. I hope this helps you get a step closer to solving your issue. Sorry I can't be of more help. Good luck.

cannot access hiddenfield value in masterpage on page_load event from child page

I'm trying to access a hiddenfield value from my masterpage that is set in my child aspx page, but cannot access it the masterpage codebehind page_load event.
Child aspx page:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="Server">
<telerik:RadStyleSheetManager ID="RadStyleSheetManager1" runat="server">
</telerik:RadStyleSheetManager>
<div class="center_content">
<div style="text-align: left">
<h2>
</h2>
</div>
<div style="text-align: left">
<uc1:Chart ID="Chart1" runat="server" />
</div>
</div>
<asp:HiddenField ID="hid1" runat="server" Value="Satellite Availability % Report" />
Master page:
<asp:Label runat="server" ID="Label1" Style="text-align: right; font-size: xx-large; color: #808080"></asp:Label>
Master page code behind: This is where I want to set the text value of the report from the child page.
protected void Page_Load(object sender, EventArgs e)
{
HiddenField hid1 = (HiddenField)MainContent.FindControl("MainContent_hid1");
if (hid1 != null)
{
Label1.Text = hid1.Value;
} }
<input type="hidden" name="ctl00$MainContent$hdnRptTitle" id="MainContent_hdnRptTitle" value="Satellite Availability % Report" />
There is no intellisense for the hdnRptTitle variable.
How can I get this to work? It seems simple enough, but don't know why it not working...
You can add the below code in your MasterPage:
HiddenField hid1 = (HiddenField)MainContent.FindControl("hid1");
if (hid1 != null)
{
Label1.Text = hid1.Value;
}
EDIT: Make sure your Label on the MasterPage is outside your ContentPlaceHolder, as I made this mistake when I first tested.
The above code should work as provided, with your control names, I'm not sure why you are using:
.FindControl("MainContent_hid1");
instead of
.FindControl("hid1");
You can use like this.
There can be multiple conterntPlaceHolder on your master page.
use the id which contains your hidden field in this case I assume that it is ContentPlaceHolder1
HiddenField hid1 = (HiddenField)ContentPlaceHolder1.FindControl("hdnRptTitle");
if (hid1 != null)
{
Label1.Text = hid1.Value;
}
There is a similar post on so
How to access content page controls from master page in asp.net
You can reference a master page and get the control like this:
VB.Net:
Dim te As HiddenField
Dim val As String
te = Me.Page.Master.FindControl("hdnRptTitle")
val = te.Value
c#:
HiddenField te = default(HiddenField);
string val = null;
te = this.Page.Master.FindControl("hdnRptTitle");
val = te.Value;
Why do you think that you can access a control in a content-page of a master-page? A MasterPage is used for multiple pages, why do you want to hardlink it with a specific page, it won't work anymore without it. If the HiddenField is essential for the operation of the master you should declare it there.
For every child page, there is a different rpt title which needs to
show up on the master page. How can I accomplish this?
Then the content page can access it's master to set the text but not vice-versa.
You could provide a public property in the master, e.g.:
public string ReportTitle
{
get { return this.LblReportTitle.Text; }
set { this.LblReportTitle.Text = value; }
}
and in the ContentPage, for example in it's Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
// assuming the type of your master is SiteMaster
var master = this.Master as SiteMaster;
if (master != null)
master.ReportTitle = hdnRptTitle.Value;
}
This approach is still linking the master with one (or multiple) of it's childs, but it would still "work" if the content-page would use a different master-type. You'd also be informed with a compiler error if somebody remove or change the property.
However, where the content stores the report-type or where the master displays it is an implementation detail and can be changed in future without breaking anything.

Repeater does not show anything after second set of data binding

I have the following repeater inside an ASCX file:
<asp:Repeater ID="repeater1" runat="server">
<HeaderTemplate>
<ul class="formList">
</HeaderTemplate>
<ItemTemplate>
<li><a href="plugins/umbracocontour/editForm.aspx?guid=<%# ((Umbraco.Forms.Core.Form)Container.DataItem).Id %>"
class="form">
<%# ((Umbraco.Forms.Core.Form)Container.DataItem).Name %></a> <small><a href="plugins/umbracocontour/editForm.aspx?guid=<%# ((Umbraco.Forms.Core.Form)Container.DataItem).Id %>">
Open form designer</a> <a href="plugins/umbracocontour/editFormEntries.aspx?guid=<%# ((Umbraco.Forms.Core.Form)Container.DataItem).Id %>">
View entries</a> </small></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
It is populated with data via a method named ShowAllForms()
private void ShowAllForms()
{
using (var formStorage = new FormStorage())
{
var list = formStorage.GetAllForms(false).OrderBy(f => f.Name).Where(form => Security.HasAccessToForm(form.Id)).ToList();
this.repeater1.DataSource = list;
this.repeater1.DataBind();
if (list.Count == 0)
{
this.paneBrowse.Visible = false;
}
}
}
and `SearchForms:
private void SearchForms()
{
var forms =
this.formRepository.GetFormByFreeText(this.txtFormSearch.Text).Where(form => Security.HasAccessToForm(form.Id)).
ToList();
this.repeater1.DataSource = forms;
this.repeater1.DataBind();
}
ShowAllForms() is called in Page_Load, if there has not been a postback, and also in the click event for the "Show All Forms" button. SearchForms() is called in the postback for the "Search Forms" button.
As a non-admin user, when I view the list of forms I see a whole bunch of them initially. I then search for a form via it's name which should return no items. So far so good. I then click the "Show All Forms" button which will execute ShowAllForms(), which is what was called to show all the forms in the first place.
However, when called a second time, ShowAllForms() does not show any form data in the repeater. To clarify, I can see that there are items returned in the forms variable, so the collection is not empty, and yet none of those items appear in the repeater.
I'm puzzled as to what could be going on here.
EDIT:
OnLoad event for the page:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.ShowAllForms();
}
}
OnInit:
protected void Page_Init(object sender, EventArgs e)
{
this.formRepository = TinyIoC.TinyIoCContainer.Current.Resolve<IFormRepository>();
}
I believe the problem is here:
if (list.Count == 0)
{
this.paneBrowse.Visible = false;
}
I don't see where you set paneBrowse's visiblity to true again.
A quick fix would be:
this.paneBrowse.Visible == (list.Count > 0);

Create Asp.net Reset Button

Is there any ways to create reset button to clear all text in text fields in asp form? When user hits the reset button, all text entered by them will clear and they are enable to enter back text in the area.
As per my knowledge there is no such reset functionality provided by Asp.Net.
We can achieve the reset like this
btnReset.Attributes.Add("onClick", "document.forms[0].reset();return false;");
Or
Like this
<input type='button' id='resetButton' value='Reset' onclick='theForm.reset();return false;'/>
Or OnClientclick of asp.net button use this theForm.reset();return false;
try this create a button with reset and in click event write ClearInputs(Page.Controls); and event will call this method.
protected void Button2_Click(object sender, EventArgs e)
{
ClearInputs(Page.Controls);
}
void ClearInputs(ControlCollection ctrls)
{
foreach (Control ctrl in ctrls)
{
if (ctrl is TextBox)
((TextBox)ctrl).Text = string.Empty;
ClearInputs(ctrl.Controls);
}
}
In the button click method, set all textbox.text.length values to 0. either do it one by one, which is the simple way, or do it by getting all controls of type textbox on the page, which is tad bit more sophisticated, but could be much less typing, depending on the number of textboxes. Definitely more maintainable.
private void ChangeBtn_Click(object sender, EventArgs e)
{
foreach(Control c in Page.Controls)
{
if (c.Controls.Count > 0)
{
foreach(Control c2 in c.Controls)
{
if (c2.GetType().ToString() == "System.Web.UI.WebControls.TextBox")
{
myspan.InnerHtml = ((TextBox)c2).Text;
((TextBox)c2).Text = ""; //or ((TextBox)c2).Text.Length = 0;
}
}
}
}
}
http://msdn.microsoft.com/en-us/library/20zys56y(v=vs.90).aspx
Create a Click event to the Button control and use the following codes below:
foreach (Control control in Page.Controls)
{
if (control is TextBox)
{
TextBox txt = (TextBox)control;
txt.Text = "";
}
}
This will save you some time to clear all the textboxes inside the web form.
Use Jquery the easiest way to find any type of control and will not have post back event.
$('input[type=text], textarea')
Use foreach loop for clearing value.
Please note that
btnReset.Attributes.Add("onClick", "document.forms[0].reset();return false;");
will not work in clearing pages that are posted back, i.e. If a text box had a value "Silly me" and has been posted back, this code will reset to the post back value which is "Silly me".
The workaround is to repost the page with cleared values - try the following code (it worked for me)
OnClientClick="document.location.href=document.location.href;"
will reload the page with cleared values...
I have multiple type of inputs in my page (TextBox, DropDownList and CheckBox), so here is how I reset them all
Put an <asp:Panel> that wraps my inputs
Run BtnClear_Click on Clear button click
Loop each inputs and reset text/selection/checked value by types
The codes
Default.aspx
<asp:Panel ID="PanelReport" runat="server">
...
<asp:TextBox ID="fldSpeedoMula" runat="server"></asp:TextBox>
<asp:DropDownList ID="ddlPlateNo" runat="server" CssClass="form-control"></asp:DropDownList>
<asp:CheckBox ID="cbCard" runat="server" />
<asp:CheckBox ID="cbCash" runat="server" />
<asp:Button ID="BtnClear" runat="server" Text="Clear" CssClass="button" OnClick="BtnClear_Click"/>
...
</asp:Panel>
Default.aspx.cs
protected void BtnClear_Click(object sender, EventArgs e)
{
// Clear all inputs
foreach (DropDownList ddl in PanelReport.Controls.OfType<DropDownList>())
{
ddl.SelectedIndex = 0;
}
foreach (TextBox fld in PanelReport.Controls.OfType<TextBox>())
{
fld.Text = string.Empty;
}
foreach (CheckBox cb in PanelReport.Controls.OfType<CheckBox>())
{
cb.Checked = false;
}
}

ASP.NET + jQuery + Dynamically Created HyperLink controls

I have an ASP.NET application that uses jQuery. My ASP.NET application dynamically generates some HyperLink elements based on some values in a database. When a user clicks one of these HyperLink elements, I want to display a jQuery dialog box that allows the user to edit the text of the HyperLink. I have this part working.
When a user clicks the "Save" button, I need to read the values of the HyperLink elements and save them back to the database. Currently, I get the initial values of the HyperLink elements. However, I cannot get any modified values. How do I get the values that were provided by the user? I have provided my .aspx and .aspx.cs code here:
test
Report:
<div id="recommendDialog" title="Number">
<table border="0" cellpadding="0" cellspacing="0">
<tr><td>Number</td></tr>
<tr><td><input id="optionName" type="text" /></td></tr>
</table>
</div>
<asp:Button ID="saveButton" runat="server" Text="Save" OnClick="saveButton_Click" />
</div>
</form>
<script type="text/javascript">
var editingID = null;
$("#recommendDialog").dialog({
autoOpen: false,
height: 200,
modal: true,
buttons: {
Cancel: function() {
$(this).dialog('close');
},
'OK': function() {
var newValue = $("#optionName").val();
if (editingID != null) {
$(editingID).attr("name", newValue);
$(editingID).html(newValue);
}
$(this).dialog('close');
}
},
close: function() {
}
});
function update_Click(link) {
editingID = "#" + link.id;
$("#optionName").val(link.name);
$('#recommendDialog').dialog('open');
}
</script>
Here is my code-behind:
public partial class _Default : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
AddHyperlinks();
}
protected void Page_Load(object sender, EventArgs e)
{}
protected void saveButton_Click(object sender, EventArgs e)
{
foreach (TableCell cell in reportTable.Rows[0].Cells)
{
HyperLink h = (HyperLink)(cell.Controls[0]);
string newValue = h.Attributes["name"];
// Save value to database here. newValue does not show
// changed values.
Console.WriteLine(newValue);
}
}
private void AddHyperlinks()
{
TableRow row = new TableRow();
for (int i = 1; i < 11; i++)
{
HyperLink hyperlink = new HyperLink();
hyperlink.NavigateUrl = "#";
hyperlink.Text = i.ToString();
hyperlink.Attributes.Add("id", "h" + i);
hyperlink.Attributes.Add("name", i.ToString());
hyperlink.Attributes.Add("onclick", "update_Click(this);");
AddLinkButtonToRow(hyperlink, row);
}
reportTable.Rows.Add(row);
}
private void AddLinkButtonToRow(HyperLink linkButton, TableRow row)
{
TableCell cell = new TableCell();
cell.Controls.Add(linkButton);
row.Cells.Add(cell);
}
}
What you're trying to do isn't possible that way. You create links every time the page is created. Although you change the name of these links in JavaScript, these values are not posted back to you.
On Sumbit, only form elements get posted back to the server (<input>s, for example), not <a> elements, so your server doesn't "know" the changes were made.
Secondly, even if you'll change the <a>s to <input>s, you still have a problem: you won't be able to find these values in reportTable.Rows[0].Cells as you expect. Normally asp.net will fill these values correctly, even for dynamically generated controls, but not here - since you've changed their names! Asp.net cannot rebind these values.
So, what should you do? One option is to add an hidden field to every cell.
On AddLinkButtonToRow, add the following:
HtmlInputHidden hidden = new HtmlInputHidden();
hidden.ID = "hidden" + linkButton.ID;
hidden.Name = hidden.ID; //so it will be posted!
hidden.Style["display"] = "none"; //better to have a CssClass
Using jQuery, which you seem to know, change the values of these input fields, not their names (something like $(editingID).parent().find(":hidden")).
Next, you might not see the values on the controls, but you can find them at Request.Form["hiddenh1"] ... Request.Form["hiddenh11"] - All input fields will names will be posted, and you know their names this time.
I'm not sure where or what "ReportTable" and it's tablecells are, but I'm guessing your problem is that you're manipulating the value of some tags on the client using jQuery, and expecting them to be posted back to the server?
This won't work. The page got rendered with known values of your HyperLink controls in ViewState. Since tags are not input types, they will not post a value back to the server on a postback, and ViewState will always re-initialize them with their original values. Any manipulation must be done on the server side.
I would recommend doing what ScottE suggests and do your update with jquery ajax.

Resources