I have a master page it has
<asp:Timer ID="masterTimer" runat="server" Interval="1000" OnTick="masterTimer_Tick"/>
<asp:UpdatePanel runat="server" ID="time" UpdateMode="Always" ChildrenAsTriggers="True">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="masterTimer" EventName="Tick"/>
</Triggers>
<ContentTemplate>
<asp:Label runat="server" ID="lblTime"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
and in code behind i have simple
protected void masterTimer_Tick(object sender, EventArgs e)
{
this.lblTime.Text = DateTime.Now.ToString("ddd MMM dd yyyy h:mm:ss tt");
}
In content page i have
Dictionary<Guid, string> data = dataClass.DataDictionary();
and then i am creating a dynamic server control of Label type in Default page (content page). Server control has property of Text. Now my problem is, on each tick it does read the correct data means data dictionary contains updated data and it does assign it to label text property but its not displaying the updated text.
I am creating my CustomeLabel like this
CustomLabel newLabel = new CustomLabel
{
Text = "Label",
Width = 200,
Height = 150,
};
this.Controls.Add(newLabel);
And below is the CustomLabel class derived from LinkLabel and it has below properties
public string Text { get; set; }
public int Width { get; set; }
public int Height { get; set; }
and
readonly LinkButton Label = new LinkButton();
and
protected override void OnLoad(EventArgs e)
{
Label.Text = Text;
}
protected override void Render(HtmlTextWriter output)
{
base.Render(output);
}
I will appreciate if somebody tells me what i need to do
This might do it for you:
Child page:
<%# Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="ChildPage.aspx.cs" Inherits="ChildPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<asp:UpdatePanel ID="MyUpdatePanel" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
public partial class ChildPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Label newLabel = new Label
{
Text = "Label",
Width = 200,
Height = 150,
};
newLabel.Text = "Label: " + DateTime.Now.ToString();
PlaceHolder1.Controls.Add(newLabel);
}
}
Related
I want the user to be able to delete a UserControl by clicking on a Delete button located inside that UserControl.
The btnAddChoice is working fine but the btnRemove is inside the UserControl and btnRemove_Click is not triggered.
Here is my ShowChoices.aspx code :
<div>
<strong>Choices</strong>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" ChildrenAsTriggers="true">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAddChoice" EventName="Click" />
</Triggers>
<ContentTemplate>
<ul class="list-unstyled">
<asp:PlaceHolder runat="server" ID="phChoices">
</asp:PlaceHolder>
</ul>
</ContentTemplate>
</asp:UpdatePanel>
</div>
Here is my ShowChoices.aspx.cs code :
protected void btnAddChoice_Click(object sender, EventArgs e)
{
Choice ctl = (Choice)LoadControl("~/Controls/Choice.ascx");
ctl.ID = "choice" + PersistedControls.Count;
int j = PersistedControls.Count + 1;
ctl.SetSummary("Choice #" + j);
phChoices.Controls.Add(ctl); // the UserControl is added here
PersistedControls.Add(ctl);
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = ctl.BtnRemoveUniqueID; // problem : BtnRemoveUniqueID = always null
trigger.EventName = "Click";
UpdatePanel1.Triggers.Add(trigger);
}
In Choice.ascx :
<asp:Button ID="btnRemove" CssClass="btn-default" runat="server" Text="Remove this choice" CausesValidation="false" OnClick="btnRemove_Click"/>
In Choice.ascx.cs
protected void btnRemove_Click(object sender, EventArgs e)
{
this.Parent.Controls.Remove(this);
List<Control> _persistedControls = (List<Control>) Session[Step2.PersistedControlsSessionKey];
_persistedControls.Remove(this);
Session[Step2.PersistedControlsSessionKey] = _persistedControls;
UpdatePanel ctl = (UpdatePanel) this.Parent.FindControl("UpdatePanel1");
if (ctl != null)
{
ctl.Update();
}
}
A user control creates a separate naming container, which means additional work is required for your update panel (the SO answer here does a good job explaining it: Trigger an update of the UpdatePanel by a control that is in different ContentPlaceHolder)
This is a fully working example of exposing a button inside a user control so it can act as a trigger and fire events in the parent page. The button is exposed using a public property on the child control, and then all of the event handlers are attached in the parent.
Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%# Register Src="~/TestChildControl.ascx" TagName="Custom" TagPrefix="TestChildControl" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" />
<div>
<asp:UpdatePanel runat="server" ID="updTest">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAddControl" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:Placeholder runat="server" ID="phControlContainer"></asp:Placeholder>
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button runat="server" ID="btnAddControl" Text="Add Control" OnClick="btnAddControl_OnClick" />
</div>
</form>
</body>
</html>
Default.aspx.cs
Note that the child controls have to be recreated on Page Load in the same order with the same IDs in order for events to fire properly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (ControlIDs != null)
{
foreach (string controlID in ControlIDs)
{
AddChildControl(controlID);
}
}
}
protected void btnAddControl_OnClick(object sender, EventArgs e)
{
var rand = new Random();
var controlID = string.Format("TestChildControl_{0}", rand.Next());
AddChildControl(controlID);
}
protected void AddChildControl(string controlID)
{
TestChildControl childControl = (TestChildControl)LoadControl("~/TestChildControl.ascx");
childControl.ID = controlID;
phControlContainer.Controls.Add(childControl);
childControl.RemoveControlButton.Click += btnRemoveControl_OnClick;
AsyncPostBackTrigger updateTrigger = new AsyncPostBackTrigger() { ControlID = childControl.RemoveControlButton.UniqueID, EventName = "click" };
updTest.Triggers.Add(updateTrigger);
SaveControlIDs();
}
private void SaveControlIDs()
{
ControlIDs = phControlContainer.Controls.Cast<Control>().Select(c => c.ID).ToList();
}
protected void btnRemoveControl_OnClick(object sender, EventArgs e)
{
var removeButton = sender as Button;
if (removeButton == null)
{
return;
}
var controlID = removeButton.CommandArgument;
var parentControl =
phControlContainer.Controls.Cast<TestChildControl>().FirstOrDefault(c => c.ID.Equals(controlID));
if (parentControl != null)
{
phControlContainer.Controls.Remove(parentControl);
}
SaveControlIDs();
}
protected IEnumerable<string> ControlIDs
{
get
{
var ids = ViewState["ControlIDs"] ?? new List<string>();
return (IEnumerable<string>) ids;
}
set { ViewState["ControlIDs"] = value; }
}
}
TestChildControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="TestChildControl.ascx.cs" Inherits="TestChildControl" %>
<div>
This is a test control
</div>
<div>
<asp:Button runat="server" ID="btnRemoveControl" Text="Remove Control" />
</div>
TestChildControl.ascx.cs
Note that here we expose the button as a read-only property so we can assign event handlers to it and access its members. I assigned the parent control ID as the CommandArgument as a matter of convenience.
using System;
using System.Web.UI.WebControls;
public partial class TestChildControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
btnRemoveControl.CommandArgument = this.ID;
}
public Button RemoveControlButton
{
get { return btnRemoveControl; }
}
}
I am trying to create a textbox dynamically using a string. and then trying to read on a buttton click.
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="textboxtest.aspx.cs" Inherits="test2.textboxtest" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<div id="TextBoxDiv" runat="server" class="asid box">
</div>
<asp:Button ID="Button1" runat="server" Text="CreateTextBox" onclick="Button1_Click" />
<asp:Button ID="Button2" runat="server" Text="ReadTextBox" onclick="Button2_Click" />
</asp:Content>
Here is the code behind.
protected void Button1_Click(object sender, EventArgs e)
{
string finalText = #"<input type=""text"" ID=""T1"" runat=""server"">
<asp:TextBox ID=""TB1"" runat=""server""></asp:TextBox>";
TextBoxDiv.InnerHtml = finalText;
}
protected void Button2_Click(object sender, EventArgs e)
{
TextBox txtAddress2 = (TextBox)Page.FindControl("TB1");
foreach (Control c in TextBoxDiv.Controls)
{
if (c is TextBox)
{
TextBox txt = (TextBox)c;
string str = txt.Text;
}
}
}
As you can see from the code i have tried to access the textbox using find control and also looping through. but both are failing.
I managed to get it to work, but by only having to create dynamic textboxes in Page_Init event. So every time there is a post back you need to re-create your dynamic controls. You can check online, they say the same thing.
So here is the client side:
<asp:PlaceHolder runat="server" id="TextBoxesHere" />
<asp:Button ID="Button1" CssClass="btn btn-primary btn-outline" runat="server"
Text="CreateTextBox" OnClick="Button1_Click" />
<asp:Button ID="Button2" CssClass="btn btn-primary btn-outline" runat="server"
Text="ReadTextBox" OnClick="Button2_Click" />
Server Side:
protected void Page_Init(object sender, EventArgs e)
{
TextBox txt = new TextBox();
txt.ID = "T1";
txt.CssClass = "form-control";
TextBoxesHere.Controls.Add(txt);
}
protected void Button1_Click(object sender, EventArgs e)
{
TextBox txt = new TextBox();
txt.ID = "T1";
txt.CssClass = "form-control";
TextBoxesHere.Controls.Add(txt);
}
protected void Button2_Click(object sender, EventArgs e)
{
TextBox txt = (TextBox)TextBoxesHere.FindControl("T1");
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "", "alert('" + txt.Text + "');", true);
}
use a Placeholder instead of a div (it will generate a div) and then add controls in the placeholder instead of using InnerHtml.
So this can be achieved like this:
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="textboxtest.aspx.cs" Inherits="test2.textboxtest" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server"></asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<asp:PlaceHolder runat="server" ID="TextBoxPlaceHolder"></asp:PlaceHolder>
<asp:Button ID="Button1" runat="server" Text="CreateTextBox" onclick="Button1_Click" />
<asp:Button ID="Button2" runat="server" Text="ReadTextBox" onclick="Button2_Click" />
</asp:Content>
Code-behind:
protected void Button1_Click(object sender, EventArgs e)
{
string finalText = #"<input type=""text"" ID=""T1"" runat=""server"">";
var textbox = new TextBox();
textbox.ID = "TB1";
this.TextBoxPlaceHolder.Controls.Add(new LiteralControl(finalText));
this.TextBoxPlaceHolder.Controls.Add(textbox);
}
protected void Button2_Click(object sender, EventArgs e)
{
TextBox txtAddress2 = (TextBox)Page.FindControl("TB1");
foreach (Control c in TextBoxDiv.Controls)
{
if (c is TextBox)
{
TextBox txt = (TextBox)c;
string str = txt.Text;
}
}
}
I have a page with a number of controls of type MyControl added dynamically. The count is stored in the ViewState, and only incremented with a button click.
In MyControl, I have a TextBox control, and a Label control. When the text is changed in the textbox, the value is multiplied by 2 and displayed in the label control.
To do this, I have added an OnTextChanged event and set AutoPostBack to true.
My problem is this: when I have any number of MyControl's on the page, and change the text in any of the textboxes, the label is updated and the values are retained on postback.
However, if I click the increment button on the page, all the values in the textboxes and labels are lost.
My code:
Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Test.Default" EnableViewState="true" %>
<html>
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
Count:
<asp:Label ID="lblCount" runat="server"></asp:Label>
<asp:Button ID="btnAdd" runat="server" OnClick="btnAdd_Click" Text="+" />
<asp:Panel ID="pnlControls" runat="server"></asp:Panel>
</form>
</body>
</html>
Default.aspx.cs
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
int count = 0;
//if not postback, then set count and store in viewstate
if (!Page.IsPostBack)
{
count = 1;
ViewState["count"] = count;
}
LoadControls();
}
protected void btnAdd_Click(object sender, EventArgs e)
{
//increment count
ViewState["count"] = (int)ViewState["count"] + 1;
pnlControls.Controls.Clear();
LoadControls();
}
private void LoadControls()
{
//add controls to page
for (int i = 0; i < (int)ViewState["count"]; i++)
{
MyControl con = (MyControl)LoadControl("MyControl.ascx");
con.ID = i.ToString();
pnlControls.Controls.Add(con);
}
//set count label
lblCount.Text = ViewState["count"].ToString();
}
}
MyControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.ascx.cs" Inherits="Test.MyControl" EnableViewState="true" %>
<div>
<asp:TextBox ID="txtField" runat="server" OnTextChanged="txtField_TextChanged" AutoPostBack="true"></asp:TextBox>
<asp:Label ID="lblAnswer" runat="server" Text="answer:"></asp:Label>
</div>
MyControl.ascx.cs
public partial class MyControl : System.Web.UI.UserControl
{
public string Text;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void txtField_TextChanged(object sender, EventArgs e)
{
lblAnswer.Text = (int.Parse(txtField.Text) * 2).ToString();
}
}
Am I missing something obvious? How can I keep the values when the button is clicked?
The reason you lose the info of MyControl(s..) is when you click the button you clear them:
pnlControls.Controls.Clear();
If you want to keep the values I recomended you to use Session variables, for example an array when you fire "txtField_TextChanged" to save "lblAnswer.Text", be carefull with the ID's to differentiate from each other in the Session variable.
Finally, I'd put "LoadControls();" inside Page_Load, outside I think It's redundant.
I am currently creating a page that a user will be able to input information and on submit it should save this information to a text file, however I seem to be unable to obtain the textbox as it appears to be undefined even when an ID is set on it, could someone please explain what I am doing wrong? As it seems to be working correctly with my btnSave method.
Backend C#:
public partial class Green_FreeShipping : System.Web.UI.Page
{
private static readonly string FILE_PATH = "~/TextFiles/Notes.txt";
private void GetNote()
{
using (TextReader tr = new StreamReader(MapPath(FILE_PATH)))
{
txtNote.Text = tr.ReadToEnd();
}
}
private void SaveNote()
{
using (TextWriter tw = new StreamWriter(MapPath(FILE_PATH)))
{
tw.Write(txtNote.Text);
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.GetNote();
}
}
protected void btnSave_Click(object sender, EventArgs e)
{
this.SaveNote();
this.GetNote();
}
}
ASP.NET code:
<%# Page Language="C#" MasterPageFile="~/admin/masters/admin.master" autoeventwireup="true" inherits="TextBox_ReadWriteToTextFile" Title="Green & Free shipping amounts" codefile="~/admin/bespoke/Green-FreeShipping.aspx.cs"%>
<%# Register TagPrefix="web" Assembly="website.Web" Namespace="website.Web" %>
<%# Register TagPrefix="sales" Assembly="website.site.Web" Namespace="website.site.Web.Sales" %>
<%# Register TagPrefix="ecom" Namespace="website.site.Web" Assembly="website.site.Web" %>
<asp:Content ID="TitleContent" ContentPlaceHolderID="TitlePlaceHolder" runat="Server">
<title>Shopfront - Green and Free shipping amounts</title>
</asp:Content>
<asp:content id="Content1" contentplaceholderid="ContentPlaceHolder1" runat="Server">
<div style="margin-bottom: 20px;">
<asp:textbox id="txtNote" runat="server" rows="5" textmode="MultiLine" width="200px" />
</div>
<asp:button id="btnSave" runat="server" onclick="btnSave_Click" text="Save" />
</asp:content>
Your asp should inherit 'Green_FreeShipping' so that the c# can have access to the controls contained in it.
I am using Google ReCaptcha V2 and it is inside an updatepanel. IF validation failed ReCaptcha disappears on postback.
I read similar topics but I have not yet found an answer that solves my problem.
Please help!
My ASPX code :
<%# Register Assembly="GoogleReCaptcha" Namespace="GoogleReCaptcha" TagPrefix="cc1" %>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<form id="formRegister" runat="server">
<asp:ScriptManager ID="ScriptManagerRegister" EnablePartialRendering="true" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanelRegister" hildrenAsTriggers="false" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Panel ID="Panel1" runat="server"></asp:Panel>
<asp:Button ID="ButtonRegister" runat="server" Text="Registrera" CssClass="btn btn-primary btn-md" /><br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</asp:Content>
My code behind C#
GoogleReCaptcha.GoogleReCaptcha ctrlGoogleReCaptcha = new GoogleReCaptcha.GoogleReCaptcha();
protected override void CreateChildControls()
{
base.CreateChildControls();
ctrlGoogleReCaptcha.PublicKey = "My Public Key";
ctrlGoogleReCaptcha.PrivateKey = "My Private Key";
this.Panel1.Controls.Add(ctrlGoogleReCaptcha);
}
protected void Page_Load(object sender, EventArgs e)
{
ButtonRegister.Click += new EventHandler(ButtonRegister_Click);
}
protected void ButtonRegister_Click(object sender, EventArgs e)
{
if (ctrlGoogleReCaptcha.Validate())
{
//submit form
Label1.Text = "Success";
}
else
{
Label1.Text = "Captcha Failed!! Please try again!!";
}
}
use this script after body
<body>
<script language="javascript" type="text/javascript">
function pageLoad()
{
$('.g-recaptcha').each(function (index, obj) {
grecaptcha.render(obj, { 'sitekey': 'yoursitekey' });
});
}
</script>