Adding and removing User control from Placeholder - asp.net

What I am trying to achieve that if a user control already added to placeholder then it will be removed otherwise will be added to it and it will be done in a LinkButton's onclick.
The code:
public partial class SiteSettings : System.Web.UI.Page {
private UserSettings UserSettingsControl;
protected void Page_Load(object sender, EventArgs e) {
System.Diagnostics.Debug.WriteLine("Pageload");
UserSettingsControl = LoadControl("~/UserControls/UserSettings.ascx") as UserSettings;
}
protected void UserLink_Click(object sender, EventArgs e) {
if (SettingsPlaceholder.Controls.Contains(UserSettingsControl)) {
System.Diagnostics.Debug.WriteLine("Contains");
SettingsPlaceholder.Controls.Remove(UserSettingsControl);
} else {
System.Diagnostics.Debug.WriteLine("Does not Contains");
SettingsPlaceholder.Controls.Add(UserSettingsControl);
}
}
}
Now it is not working. And I am getting:
Pageload // on first time load
Pageload // on first time click
Does not Contains // on first time click
Pageload // on second time click
Does not Contains // on second time click
in the Output window.
How can I achieve this? I also tried to store it into ViewState, but since UserControl is not serializable so that didn't worked.
The aspx page is:
<telerik:RadAjaxManager ID="AjaxManager" runat="server">
<AjaxSettings>
<telerik:AjaxSetting AjaxControlID="UserLink">
<UpdatedControls>
<telerik:AjaxUpdatedControl ControlID="SettingsPanel" LoadingPanelID="LoadingPanel" UpdatePanelRenderMode="Block" />
<telerik:AjaxUpdatedControl ControlID="PlaceHolderPanel" />
</UpdatedControls>
</telerik:AjaxSetting>
</AjaxSettings>
<ClientEvents OnResponseEnd="respondEnd" />
</telerik:RadAjaxManager>
<asp:Panel ID="SettingsPanel" runat="server">
<telerik:RadSplitter ID="MainSplitter" runat="server" MinHeight="200" Width="100%"
OnClientLoaded="splitterLoaded" OnClientResized="splitterLoaded">
<telerik:RadPane ID="LeftPane" runat="server" MaxWidth="250" Width="150" MinWidth="150" CssClass="left-rounded-corner settings-splitter-left">
<asp:Panel runat="server">
<asp:LinkButton ID="UserLink" runat="server" onclick="UserLink_Click" Text="User Settings" />
</asp:Panel>
</telerik:RadPane>
<telerik:RadSplitBar ID="Splitbar" runat="server" CollapseMode="Forward" />
<telerik:RadPane ID="RightPane" runat="server" CssClass="right-rounded-corner settings-splitter-right">
<asp:Panel ID="PlaceHolderPanel" runat="server" Height="100%">
<asp:PlaceHolder runat="server" ID="SettingsPlaceholder" />
</asp:Panel>
</telerik:RadPane>
</telerik:RadSplitter>
</asp:Panel>
<telerik:RadAjaxLoadingPanel ID="LoadingPanel" runat="server" />
Edit:
Modified code:
public partial class SiteSettings : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
AddUserSettings();
}
}
public UserControl UserSettingsControl {
get {
if (ViewState["UserSettings"] == null) {
ViewState["UserSettings"] = LoadControl("~/UserControls/UserSettings.ascx") as UserSettings;
}
return (UserControl)ViewState["UserSettings"];
}
}
public UserControl SpaceSettingsControl {
get {
if (ViewState["SpaceSettings"] == null) {
ViewState["SpaceSettings"] = LoadControl("~/UserControls/SpaceSettings.ascx") as SpaceSettings;
}
return (UserControl)ViewState["SpaceSettings"];
}
}
protected void SettingsLink_OnCommand(object sender, CommandEventArgs commandEventArgs) {
switch (commandEventArgs.CommandName) {
case "User":
AddUserSettings();
break;
case "Space":
AddSpaceSettings();
break;
}
}
private void AddUserSettings() {
AddSettings(UserSettingsControl);
}
private void AddSpaceSettings() {
AddSettings(SpaceSettingsControl);
}
private void AddSettings(UserControl control) {
SettingsPlaceholder.Controls.Add(control);
}
}

Create a Property in your WebForm like below.
public UserSettings UserSettingsControl
{
get
{
if (Session["MyControl"] == null)
Session["MyControl"] =
LoadControl("~/UserControls/UserSettings.ascx") as UserSettings;
return (UserSettings)Session["MyControl"];
}
}
Now you can access the memory of UserSettingsControl. As it will persist across the Postback. In the original code, the UserSettingsControl was being reset to null across PostBack.
By end of the Page Life Cycle all the controls created at runtime
will be disposed. Finally, you cannot find the control created at
runtime after Postback. Only Recreation of the same control will be
required on each PostBack.

You could just not use a PlaceHolder and have the control there the whole time. Then the linkButton could toggle the visibility of the control.
The main problem is that the you are adding the control to the page linkButton click. Dynamically added controls work best when added in the Page_Init and Page_PreInit this allows them to maintain their ViewState. Also they have to be added to the placeholder on every postback. If in your example another control causes a postback after the SettingsControl is added to the placeholder, then the SettingsControl will disappear because it is not being added on every postback.

Related

Change session variable for all clicks except for one button in a page

I have got 10 button/Links in aspx page. I need to maintain a session variable on only ONE button click and for all other 9 click/action I need to change the value in session variable.
How can I get this in a best way, instead of writing in those 9 click actions.
Please suggest
You can re-use the same event for multiple buttons, and check the 'sender' to see which button was clicked.
Markup:
<asp:Button ID="Button1" runat="server" OnClick="GenericButtonClick" Text="Button" />
<asp:Button ID="Button2" runat="server" OnClick="GenericButtonClick" Text="Button" />
CS:
protected void GenericButtonClick(object sender, EventArgs e)
{
Button button = sender as Button;
switch(button.ID)
{
case "Button1":
//Maintain Session Variable
break;
default:
//Change Value in Session Variable
break;
}
}
You then set all your buttons to use the same event handler
I use mostly the command event handler instead of click, so in aspx side, you would have something like this:
<asp:Button ID="Button1" runat="server" OnCommand="DoSomething" CommandName="SetSession" CommandArgument="true" />
<asp:Button ID="Button2" runat="server" OnCommand="DoSomething" CommandName="SetSession" CommandArgument="false" />
<asp:Button ID="Button3" runat="server" OnCommand="DoSomething" CommandName="SetSession" CommandArgument="false" />
And in the back end cs file, there would be only one event handler like this:
protected void DoSomething(object sender, CommandEventArgs e)
{
if (e.CommandArgument.ToString() == "true")
{
// set session
}
}
The benefit of using CommandEventHandler is that even later on you change the button to ImageButton or LinkButton, you don't need to change the event signature, it works for all.
You can make a property in which you can set the session value and you can also get value from this property. I have made it private because it is used only in that page where you need.
private static string SetGetSession
{
set { HttpContext.Current.Session["Mairaj"] = value; }
get { return HttpContext.Current.Session["Mairaj"].ToString(); }
}
Here is how you can use it
protected void btnOne_Click(object sender, EventArgs e)
{
SetGetSession = "Mairaj";
}
protected void btnTwo_Click(object sender, EventArgs e)
{
SetGetSession = "Ahmad";
}
protected void btnTh_Click(object sender, EventArgs e)
{
SetGetSession = "Minhas";
}
If you want it to be used in other pages as well you can make a class and make this property public you will be able to access it everywhere.

Rad Datagrid binds in page load but not in another function?

This one's really stumping me. And it looks simple. I have a telerik: RadGrid on an aspx page and I'm using a web service to get a table and bind it. I bind it once on page_load and when a node from a tree is clicked i want to bind it again displaying new info. However, when trying to bind from this function the grid comes up null. For right, now I'm using the same service call to bind.
Here's my server code:
protected void Page_Load(object sender, EventArgs e)
{
using (ServiceReference1.Service1SoapClient myService = new ServiceReference1.Service1SoapClient())
{
CurrentDemog = Convert.ToInt32(Session["demog"].ToString());
DataTable lookupTbl = myService.getTable();
LookupGrid.DataSource = lookupTbl;
LookupGrid.DataBind();
}
}
protected void LookupsTree_NodeClick(object sender, Telerik.Web.UI.RadTreeNodeEventArgs e)
{
RadTreeNode currNode = e.Node;
if (currNode.Nodes.Count == 0) {
if (currNode.ParentNode.Text != "Treatments" && !String.IsNullOrEmpty(currNode.Text))
{
selectedNode = currNode.Text;
using (ServiceReference1.Service1SoapClient myService = new ServiceReference1.Service1SoapClient())
{
Util.ClearGrid(ref LookupGrid);
DataTable lookupTbl = myService.getTable();
LookupGrid.DataSource = lookupTbl;
LookupGrid.DataBind();
}
}
}
}``
Here's my client code:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
<AjaxSettings>
<telerik:AjaxSetting AjaxControlID="LookupGrid">
<UpdatedControls>
<telerik:AjaxUpdatedControl ControlID="LookupGrid"></telerik:AjaxUpdatedControl>
</UpdatedControls>
</telerik:AjaxSetting>
</AjaxSettings>
</telerik:RadAjaxManager>
<telerik:RadGrid ID="LookupGrid" runat="server" BackColor="Gray"
BorderColor="#404040" BorderStyle="Solid" CellSpacing="0" GridLines="None"
Skin="MetroTouch">
</telerik:RadGrid>
You need to have a Page.IsPostback in your Page_Load method. Otherwise data will be loaded every time you do anything that causes page to be reloaded.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
using (ServiceReference1.Service1SoapClient myService = new ServiceReference1.Service1SoapClient())
{
CurrentDemog = Convert.ToInt32(Session["demog"].ToString());
DataTable lookupTbl = myService.getTable();
LookupGrid.DataSource = lookupTbl;
LookupGrid.DataBind();
}
}
}
What happens here is that you load your grid view and click the button. When you do this Page_Load method is called before the event handler. This most probably causes if statements in the event handler to be false causing data not to be loaded.
Here is a good reading on this topic: ASP.NET Page Life Cycle Overview

Set updatepanelanimationextender TargetControId at codebehind

Inside usercontrol I have updatepanelanimationextender, when I add this control to a webpage I want to pass updatepanel's Id as parameter to control's property.
Usercontrol:
public partial class Controls_UpdateProgress : System.Web.UI.UserControl
{
public string UpdatePanelID { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
UpdatePanelAnimationExtender1.TargetControlID = UpdatePanelID;
}
}
}
<cc1:updatepanelanimationextender id="UpdatePanelAnimationExtender1" runat="server" >
<Animations>
<OnUpdating>
<Parallel duration="0" >
<ScriptAction Script="onUpdating();" />
</Parallel>
</OnUpdating>
<OnUpdated>
<Parallel duration="0">
<ScriptAction Script="onUpdated();" />
</Parallel>
</OnUpdated>
</Animations>
</cc1:updatepanelanimationextender>
WebPage: UpdatePanel1 is an id of the updatepanel.
<uc1:UpdateProgress ID="UpdateProgress1" runat="server" UpdatePanelID="UpdatePanel1" />
I get error:
The TargetControlID of
'UpdatePanelAnimationExtender1' is not
valid. The value cannot be null or
empty.
The AJAX control extenders do not store their TargetControlID in the ViewState (I checked in System.Web.Extensions 3.5 with Reflector and that property only gets/sets a private member). Thus, the value you stored is lost on postback.
You'll have to store the value in every request:
protected void Page_Load(object sender, EventArgs e)
{
UpdatePanelAnimationExtender1.TargetControlID = UpdatePanelID;
}
To avoid that exception, you should first make sure that UpdatePanelID is not null...
if (!IsPostBack) {
if (UpdatePanelID != Null) {
UpdatePanelAnimationExtender1.TargetControlID = UpdatePanelID;
}
}
If you desire to set the property of the UpdatePanelID from the parent page programmatically you will need to cast UpdateProgress1 as a Controls_UpdateProgress instance. To do that, do something like this...
((Controls_UpdateProgress)UpdateProgress1).UpdatePanelID = "ThisIsTheIdYouWishToSet";

Access Master Page Control

I am using a UserControl Which is present in the Master Page. I need to access a Master page control in the UserControl. I need your suggestions.
The Scenario is A label is present in the Master Page. Based upon selections in the usercontrol i need to modify the masterpage label. The UserControl is present in the Master page itself not in the content place holder.
Create a public method (or public property) in the master page to modify your label and in the UserControl you are able to call it, through the Page.master object:
YourMasterPageClass master = Page.master as YourMasterPageClass;
if(master != null)
{
master.YourEditMethod("hello");
}
Quick and Easy way is to create event in control and handle in master like this:
//Control aspx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="TestControl.ascx.cs"
Inherits="TestControl" %>
<div style="width:300px;border:2px groove blue;">
<asp:Button ID="btn1" runat="server" Text="One" onclick="btn_Click" />
<asp:Button ID="btn2" runat="server" Text="Two" onclick="btn_Click" />
<asp:Button ID="btn3" runat="server" Text="Three" onclick="btn_Click" />
<asp:Button ID="btn4" runat="server" Text="Four" onclick="btn_Click" />
</div>
//Control C#
namespace Controls
{
public partial class TestControl : System.Web.UI.UserControl
{
public delegate void UserChoice(TestEventArgs e);
public event UserChoice OnUserChoice;
protected void btn_Click(object sender, EventArgs e)
{
if (OnUserChoice != null)
OnUserChoice(new TestEventArgs(((Button)sender).Text));
}
}
public class TestEventArgs : EventArgs
{
private string _value;
public TestEventArgs(string str)
{
_value = str;
}
public string Message
{
get { return _value; }
}
}
}
//MasterPage Code
protected void Page_Load(object sender, EventArgs e)
{
test1.OnUserChoice += new
Controls.TestControl.UserChoice(test1_OnUserChoice);
}
void test1_OnUserChoice(ROMS.Intranet.Controls.TestEventArgs e)
{
MasterLabel.Text = e.Message;
}
MasterLabel is name of the label in master page.
test1 is the control in master page.

Setting viewstate on postback

I am trying to set a ViewState-variable when a button is pressed, but it only works the second time I click the button. Here is the code-behind:
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
lblInfo.InnerText = String.Format("Hello {0} at {1}!", YourName, DateTime.Now.ToLongTimeString());
}
}
private string YourName
{
get { return (string)ViewState["YourName"]; }
set { ViewState["YourName"] = value; }
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
YourName = txtName.Text;
}
Is there something I am missing? Here is the form-part of the design-file, very basic just as a POC:
<form id="form1" runat="server">
<div>
Enter your name: <asp:TextBox runat="server" ID="txtName"></asp:TextBox>
<asp:Button runat="server" ID="btnSubmit" Text="OK" onclick="btnSubmit_Click" />
<hr />
<label id="lblInfo" runat="server"></label>
</div>
</form>
PS: The sample is very simplified, "use txtName.Text instead of ViewState" is not the correct answer, I need the info to be in ViewState.
Page_Load fires before btnSubmit_Click.
If you want to do something after your postback events have fired use Page_PreRender.
//this will work because YourName has now been set by the click event
protected void Page_PreRender(object sender, EventArgs e)
{
if (Page.IsPostBack)
lblInfo.InnerText = String.Format("Hello {0} at {1}!", YourName, DateTime.Now.ToLongTimeString());
}
The basic order goes:
Page init fires (init cannot access ViewState)
ViewState is read
Page load fires
Any events fire
PreRender fires
Page renders

Resources