Retain Style Properties on postback - asp.net

I have a div and 4 drop-down controls.
Default div is hidden using Style="display:none".
First drop-down don't have autopostback event.
Div's display property is changed on few values of 1st drop-down. Once its is visible. User can change values in drop-down field 2/3/4 which is having auto postback true.
As user changes value in any of the 2-5 drop-down controls, postback triggers and set the display property of that Div to Style="display:none".
How can I retain display property of div.
This is on .aspx page

The styles are not part of the data that are contained in the PostBack. In order to include them, you can create a hidden field on the page that you also set whenever your client code changes the visibility of the div.
<asp:HiddenField ID="hidden" runat="server" />
When the PostBack arrives at the server, you evaluate the Value property of the hidden field and set the style on the div so that it matches the state that was stored in the hidden field. In order to be able to change the style on the div in .NET code, you need to make sure that runat="server" is specified:
<div ID="myDiv" runat="server">
<!-- ... -->
</div>
Sample
The following sample shows how you can use a hidden field to transfer the visibility to the server and restore it on the client. In ASPX, there is the div, the hidden field to store the visiblity and a script that sets the visiblity of the div and also the value of the hidden field:
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<div id="myDiv" runat="server" style="display:none;">
Div is visible
</div>
<asp:HiddenField ID="myHidden" runat="server" />
<input type="button" value="Toggle visiblity" onclick="javascript:toggleDiv()" />
<asp:Button ID="btn" runat="server" Text="Postback" />
<script type="text/javascript">
function toggleDiv()
{
$(myDivId).toggle();
$(myHiddenId).val($(myDivId).css('display'));
}
</script>
</asp:Content>
Important to note is that the div and the hidden fields get special ASP.NET client ids that do not necessarily match the ids of the tags in the ASPX-file. Therefore, I register a startup script that defines variables with the ids (myDivId and myHiddenId):
protected void Page_Load(object sender, EventArgs e)
{
ClientScript.RegisterStartupScript(GetType(), "DivId",
"var myDivId = '#" + myDiv.ClientID + "';" + Environment.NewLine +
"var myHiddenId = '#" + myHidden.ClientID + "';",
true);
}
When a postback occurs, the value of the hidden field is transferred to the server and can be used. I've defined a PreRender event handler, that restores the visibility of the div:
protected void Page_PreRender(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(myHidden.Value))
myDiv.Style[HtmlTextWriterStyle.Display] = "none";
else
myDiv.Style[HtmlTextWriterStyle.Display] = myHidden.Value;
}

Related

Where to catch user control properties being wrapped to be loaded inside a modal?

I have a user control which has a public property (e.g. AlarmID) and this control is wrapped inside a div and when user presses a button on the page, in code-behind the public property of that user control becomes set. then a ScriptManager.RegisterStartupScript is called to show a modal popup which is a div wrapping that control.
My problem is that although in code-behind I first set the public property of that user control, but when the modal popup shows that user control, I cannot access that property
I used Control_PreRender, and Control_Load events but none of them were able to show the correct value of that property in a label inside that control.
For more clarification, here is my code in the code-behind of the control:
protected void Control_Load(object sender, EventArgs e)
{
lblAlarmCode.Text = alarmID.ToString();
}
public int AlarmID
{
get
{
return this.alarmID;
}
set
{
this.alarmID = value;
}
}
What is the exact life-cycle event in which I can catch the property to be shown correctly by that label?
Thanks
Make sure that the modal is attached to the <form> element on the page otherwise it will not be a part of the page lifecycle at all.
Just as a sample, not saying this is your code, but I had to use something similar in order to have <asp:Textbox> and <asp:Button> controls to be brought back and forth across the Request
ASPX code:
<asp:Panel runat="server" ID="pnlWorkItem">
<fieldset>
<legend></legend>
<label>Job Code</label>
<asp:DropDownList runat="server" ID="ddlJobCode" Width="50%" />
<label>Hours</label>
<asp:TextBox runat="server" ID="txtHours" />
</fieldset>
<fieldset>
<legend></legend>
<p><asp:Button runat="server" ID="btnAddWorkItem" OnClick="btnAddWorkItem_Click" text="Add Work Item" /></p>
</fieldset>
</asp:Panel>
Javascript:
$(function () {
var workItemPanel = $("#<%= pnlWorkItem.ClientID %>");
workItemPanel.hide();
$("#add-work").on("click", function () {
$(workItemPanel).dialog({
width: 450,
height: 300
}).parent().appendTo($("form:first"));
});
});
It will append your element to the form element generated by ASP.net and should have your properties set and carried across.
One solution is to set the label in setter. However there might be other solutions but this ways is just working.

RadGrid Edit Popup

I have a RadGrid that opens a PopUp window for updating records. In the edit popup I have a combobox where that has on selectedindex changed event. In that event I am trying to set HiddenFields that are on the page of the grid. Meaning that the hidden Fields are not in the same scope of the grid.
page.aspx
<div>
<RadGrid runat="server" ID="GlJournalEntryGrid" Height="300px" Width="1400px"
AutoGenerateColumns="False" OnNeedDataSource="GlJournalEntryGrid_NeedDataSource"
OnItemCommand="GlJournalEntryGrid_ItemCommand"
OnItemDataBound="GlJournalEntryGrid_ItemDataBound">
... Edit PopUp and controls....the comboBox that updates one of the other HF below...
</RadGrid>
</div>
<div id="HiddenFieldsForGlChartLU">
<asp:HiddenField runat="server" ID="jegAccountHF" />
<asp:HiddenField runat="server" ID="jegCompanyHF" />
<asp:HiddenField runat="server" ID="jegDivisionHF" />
<asp:HiddenField runat="server" ID="jegRegionHF" />
<asp:HiddenField runat="server" ID="jegDepartmentHF" />
</div>
code-Behind
protected void jegCompany_ComboBox_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
#region Set HiddenField for control so accessible by javascript
if (cbCompany.SelectedValue != null)
jegCompanyHF.Value = cbCompany.SelectedValue;
else
jegCompanyHF.Value = "";
#endregion Set HiddenField for control so accessible by javascript
...
}
You are triggering a server-side event on the SelectedIndexChanged event. This means your popup is posting the information about the item selected in the combobox to the server. You want the data to be presented in a hidden field in the parent browser window on the client.
In order to update that information on the client, you have two options:
Write some Javascript from the child window to send the data to the
parent window.
In your SelectedIndexChanged event write the data to session and then trigger a refresh of
the parent window to load the data from session

How can I access the attributes of a <span> element inside of an asp.net RepeaterItem?

I'm trying to alter the CSS class of a span that is positioned within an Asp.net RepeaterItem. The span element also has other tags inside of it (radio button).
The markup is similar to this:
<asp:Repeater>
<ItemTemplate>
<span class="spanClass" runat="server">
<label>
<asp:RadioButton id="rbID">
</asp:RadioButton>
</label>
</span>
</ItemTemplate>
</asp:Repeater>
I'm able to edit the radio button by using the following:
rb = (RadioButton)(repeaterItem.FindControl("rbID");
rb.Checked = true;
//this works
However, when using a similar piece of code to grab the span, it fails with an InnerHtml exception because the span is not a literal control:
span = (GenericHtmlControl)(repeaterItem.FindControl("spanID");
span.Attributes.Add("class", "ClassToAdd");
//this fails
The reading I've done says that this is the case because the span is not a literal control because it has other server controls within it (the radio button).
Is there a way to access the attributes of the <span> in question?
Change your span like this:
<span id="spanID" runat="server">
and then this in your code behind:
protected void myRep_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item)
{
HtmlGenericControl x = (HtmlGenericControl)e.Item.FindControl("spanID");
x.Attributes["class"] = "myClass";
}
}
You could add a field called "ClassToAdd" to the collection you are binding to the repeater. Then simply use Eval to display it. (For example, if you are binding the repeater to a DataTable, you could add a new Column called ClassToAdd and set the values appropriately in the code behind.)
<asp:Repeater>
<ItemTemplate>
<span class="<%#Eval("ClassToAdd")%>">
</span>
</ItemTemplate>
</asp:Repeater>

asp:ListBox SelectedValue not setting (dynamically or when clicked)

I have an asp:ListBox that is populated dynamically from js based on the selected value of another asp:List box. The problem is that the second list box always returns a SelectedValue of "" regardless of whether i set lstBox.selectedIndex = 0 or actually select an item in the list.
.js to add to list then set default selected item
var Option = document.createElement("option");
lstId = document.getElementById(lstId);
Option.text = lstItem;
lstId.add(Option);
lstId.selectedIndex = 0;
.vb to get selected value
Dim selSchedule As String = lstCRMSched.SelectedValue
Now as this list is populated by javascript i had to set my #page EnableEventValidation = "false" otherwise the postback that came later would fail.
Side note: I'm noticing that asp.net doesn't like it when you use hidden divs as overlays that are unhidden based on menu selections as everything it does requires a postback, which wipes out the state of the other divs. Should i just have 10 .aspx files one for each div and just switch locations from the codebehind using sessions to transfer things like selected values and data that is to be shown in another div?
You can access the SelectedValue of the drop down list through the Request object since every element in the form that has a name is submitted in the request.
You simply need to do this:
Dim selSchedule As String = Request[lstCRMSched.UniqueID]
Now, this will work just because you disabled EventValidation on the page. The error you were getting is completely normal. ASP.NET is just making sure that no one sends data that wasn't rendered by the server initially to prevent attacks. If you were to keep the EventValidation enabled on the page, you'd need to register the list for Validation via ClientScriptManager.RegisterForEventValidation
If you add items to the dropdownlist on the client these items are not persisted on the server!
But you may try saving dynamically added items (text-value-pairs) within some hidden input fields and parse them out on the server. See this link for a working example. For your example you will also have to save your selectedIndex within another hidden field to be able to access it on the server.
EDIT
demo.aspx
<script type="text/javascript">
function saveValue() {
var hiddenField1 = document.getElementById("hiddenField1");
hiddenField1.value = "hello world";
}
</script>
<form id="Form1" method="post" runat="server">
<input type="hidden" id="hiddenField1" name="hiddenField1" value="" />
<asp:Button ID="btnPostBack" runat="server" Text="PostBack"
OnClientClick="saveValue()" onclick="btnPostBack_Click" />
</form>
demo.aspx.cs
protected void btnPostBack_Click(object sender, EventArgs e)
{
Debug.WriteLine("Value of hiddenField1: " + Request["hiddenField1"]);
Debugger.Break();
}
This one worked for me. I got "hello world" on the server.
EDIT 2
Icarus pointed out that you can always access any submitted element to the server by referring to the Request object and of course he is absolutelly right! According to your question I thought you'd like to have access to all dynamically created items - and that is - with solution shown below - not possible.
aspxPage
<script type="text/javascript">
function saveToList() {
var ListBox1 = document.getElementById("ListBox1");
var ListBox2 = document.getElementById("ListBox2");
var Option = document.createElement("option");
Option.text = ListBox1.options[ListBox1.selectedIndex].text;
ListBox2.add(Option);
ListBox2.selectedIndex = 0;
}
</script>
<form id="Form1" method="post" runat="server">
<asp:ListBox ID="ListBox1" runat="server">
<asp:ListItem Text="entry1" Value="1" />
<asp:ListItem Text="entry2" Value="2" />
<asp:ListItem Text="entry3" Value="3" />
<asp:ListItem Text="entry4" Value="4" />
</asp:ListBox>
<asp:ListBox ID="ListBox2" runat="server" Width="100"></asp:ListBox>
<input id="Button1" type="button" value="Save to List" onclick="saveToList()" />
<asp:Button ID="btnPostBack" runat="server" Text="PostBack" OnClick="btnPostBack_Click" />
codeBehind
protected void btnPostBack_Click(object sender, EventArgs e)
{
Debug.WriteLine("SelectedValue of ListBox2: " + Request["ListBox2"]);
// no access to all other clientSide created items in ListBox2
Debugger.Break();
}

Load specific part in webpage?

See below image first.
we have one sidebar navigation(ajax accordion control asp.net)
now when ever user click on link inside side bar related page(content) should display in Content goes here region.
As per given instruction entire page should not be refreshed or in other word in Back Button should not work(In Internet Explorer).
what should be the way to achieve this functionality?
what should be the best suggestion for that?
EDIT: navigation tree is inside MasterPage and Content goes region is in side content page of master page
please suggest me.....
thank you so much....
The Easiest way is to Wrap your side navigation & the Content placeholder in an UpdatePanel. Set the TreeView in the side bar as the UpdateTrigger for the update Panel. But, this approach is a little inefficient.
A slightly better way is ti just wrap the Content Placeholder in an Update Panel, along with a HiddenField in it. Upon a selection in the sidebar, update the HiddenField Value with JavaScript and then refresh the update Panel.
According to:
As per given instruction entire page should not be refreshed or in other word in Back Button should not work(In Internet Explorer).
And
sidebar tree view is in master page and Content goes here region is content page
If my understanding is correct, I think you do not need to place your TreeView control in your master page because you only want one page loading dynamically the content based on the selection of your tree view. So...Why is this important? Well if you place your tree view in your page you can use an UpdatePanel to avoid full posts.
Output of the following code
The following code covers the next points:
A TreeView control is embedded in a UserControl and placed in an ASPX page (left side)
The menu contorl exposes an event that is raised whenever the selected node changes, this event is handled in the ASPX page to dynamically load user controls depending on the user selection on the right side of the page, only one content is loaded at a time.
The controls are embedded in an UpdatePanel therefore you won't change your page and your back button in your browser won't be affected
Note: the user controls keep their state across post backs
(I'm not sure if this is the best way to do it, perhaps you could try to find a solution using only ajax, and avoid the use of the evil updata panels, but certainly this is a way to do it)
I'll try to simplify the code to reduce the size of the post, I will just post the code of one user control, the other one is exactly the same I just changed its title to difference them on the page
ASCX Menu
<asp:TreeView ID="TreeView1" runat="server" onselectednodechanged="Unnamed2_SelectedNodeChanged">
<Nodes>
<asp:TreeNode Text="link1" />
<asp:TreeNode Text="link2" />
</Nodes>
<SelectedNodeStyle Font-Bold="True" Font-Italic="True" />
</asp:TreeView>
ASCX Menu code behind
public event Action<string> MenuChanged = delegate { };
protected void Unnamed2_SelectedNodeChanged(object sender, EventArgs e)
{
this.MenuChanged(this.TreeView1.SelectedNode.Text);
}
ASPX
<asp:ScriptManager runat="server" ID="sm" />
<asp:UpdatePanel runat="server" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:HiddenField runat="server" ID="currentControl" />
<table border="0" cellpadding="0" cellspacing="0" width="90%" align="center">
<tr>
<td style="width:50%; background-color: Silver">
<menu:TreeViewMenu runat="server" ID="myTreeViewMenu" OnMenuChanged="myTreeViewMenu_MenuChanged" />
</td>
<td style="width:50%; background-color: Aqua">
<p>Result:</p>
<asp:Panel runat="server" ID="myPanel">
</asp:Panel>
<asp:Label ID="lblMessage" runat="server" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
ASPX code behind
protected void Page_Init(object sender, EventArgs e)
{
if (this.IsPostBack)
{
var cc = this.Request.Form["currentControl"];
if (!string.IsNullOrWhiteSpace(cc))
{
var uc = this.LoadControl(this.Server.HtmlDecode(cc));
this.myPanel.Controls.Add(uc);
}
}
}
protected void myTreeViewMenu_MenuChanged(string e)
{
this.myPanel.Controls.Clear();
switch (e)
{
case "link1":
var cc1 = "~/Content1.ascx";
this.currentControl.Value = this.Server.HtmlEncode(cc1);
var uc1 = this.LoadControl(cc1);
this.myPanel.Controls.Add(uc1);
this.lblMessage.Text = "Updated from: link1";
break;
case "link2":
var cc2 = "~/Content2.ascx";
this.currentControl.Value = this.Server.HtmlEncode(cc2);
var uc2 = this.LoadControl(cc2);
this.myPanel.Controls.Add(uc2);
this.lblMessage.Text = "Updated from: link2";
break;
default:
this.lblMessage.Text = "Updated from default: " + e;
break;
}
}
ASCX
<h1>Content 1</h1>
<asp:TextBox runat="server" ID="txt" />
<asp:Button Text="Process data..." runat="server" OnClick="button_Click" />
<asp:Button Text="Just post" runat="server" />
<asp:Label ID="lblMessage" runat="server" />
ASCX Code Behind
protected void button_Click(object sender, EventArgs e)
{
this.lblMessage.Text = this.txt.Text;
}
You can simply copy-paste this code to test it yourself, this should work
Jupaol's answer works fine but 1 thing need to mention, I came across the problem after implemented Jupaol's idea, the first time I called the user control immediately after I click menu, the button with in the ascx works fine, but if I switch to 2nd one, first click of the button on the 2nd control will not fire on first click, this is because we do not have a "static" ID of the control. It took me almost 3 days to finally figure out why this is happening. so here's part of my code to make. I'm leaving this message in hope that anyone who read this afterwards will make the use of it.
if (!string.IsNullOrEmpty(controlPath))
{
PlaceHolder1.Controls.Clear();
UserControl uc = (UserControl)LoadControl(controlPath);
/**note below LastLoadedControl is anything that could
* be unique to the called control so every time when call back
* it will not confuse the back end so the first fire of eg. a button
* on that loaded control will work
*/
uc.ID = LastLoadedControl;
PlaceHolder1.Controls.Add(uc);
}
I'll also need to thank Jupaol's great contribution so that I can get my site running.

Resources