I have a method that changes the text of the controls on my site.
These changes should be visible right when the user loads the page.
But the changes are first visible after the next postback.
I tried to call it in Page_PreInit, Page_Init, Page_PreLoad and and all the other methods described here.
But none of them worked.
Some code:
The class with the methods: (partly)
namespace MyNamespace {
public class ControlTextCorrection {
Page _page;
public ControlTextCorrection(Page page) {
_page = page;
}
public void Correct() {
HtmlEncodeControls(_page);
}
private void HtmlEncodeControls(Page page) {
Control control = (Control)page;
HtmlEncodeControls(control);
}
private void HtmlEncodeControls(Control parentControl) {
if (!parentControl.HasControls()) {
return;
}
foreach (Control control in parentControl.Controls) {
if (control.HasControls()) {
HtmlEncodeControls(control);
}
if (control is Label) {
Label label = (Label)control;
label.Text = HtmlTextCorrection(label.Text);
}
else if (control is CheckBox) {
CheckBox checkBox = (CheckBox)control;
checkBox.Text = HtmlTextCorrection(checkBox.Text);
}
//Correction for more controls...
}
}
protected string HtmlTextCorrection(string text) {
bool encode = true;
while (encode) {
string newText = _page.Server.HtmlDecode(text);
if (newText == text) {
encode = false;
}
text = newText;
}
text = _page.Server.HtmlEncode(text);
return text;
}
}
}
Example for calling the method:
protected void Page_PreLoad(object sender, EventArgs e) {
ControlTextCorrection correction = new ControlTextCorrection(this.Page);
correction.Correct();
}
So, where (when) should i call it so that the changes are visible at the first sight of the site?
Related
I started making a small program. The form contains checkbox1,2,3,4,.... and textbox1,2,3,4,5.... there is a code that looks at which of the checkboxes are marked. If there is any possibility to link textbox and checkbox. So that when a code marked with a checkbox is detected, the text is taken from the textbox given to it and transferred to the RichTextBox, using AppendText. Below is a sample code with a cyclic check of all the checkboxes on the form for the presence of checked on my form.
foreach (Control control in this.tabControl1.TabPages[0].Controls) //цикл по форме с вкладками
{
if (control as CheckBox != null) // проверка на пустое значение
{
if (control.Visible == true)// проверка на видимость
{
if ((control as CheckBox).Checked)// проверка на чек
{
}
else if ((control as CheckBox).Checked == false)
{
}
}
}
Use the following method to get CheckBox controls.
public static class ControlExtensions
{
public static IEnumerable<T> Descendants<T>(this Control control) where T : class
{
foreach (Control child in control.Controls)
{
if (child is T thisControl)
{
yield return (T)thisControl;
}
if (child.HasChildren)
{
foreach (T descendant in Descendants<T>(child))
{
yield return descendant;
}
}
}
}
}
In the form, use a Dictionary to pair CheckBox to TextBox. You can also check for visibility in the Where.
public partial class Form1 : Form
{
private readonly Dictionary<string, TextBox> _dictionary =
new Dictionary<string, TextBox>();
public Form1()
{
InitializeComponent();
_dictionary.Add("checkBox1", textBox1);
_dictionary.Add("checkBox2", textBox2);
_dictionary.Add("checkBox3", textBox3);
_dictionary.Add("checkBox4", textBox4);
_dictionary.Add("checkBox5", textBox5);
}
private void button2_Click(object sender, EventArgs e)
{
var list = tabControl1.Descendants<CheckBox>().ToList();
var #checked = list.Where(x => x.Checked).ToList();
var notChecked = list.Where(x => !x.Checked).ToList();
foreach (var checkBox in #checked)
{
TextBox textBox = _dictionary[checkBox.Name];
}
}
}
Create a UserControl with CheckBox and TextBox components. Create properties Checked and TextForAdd:
namespace Sort.UserPanel
{
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public bool Checked { get { return checkBox1.Checked; } }
public string TextForAdd { get { return textBox1.Text; } }
}
}
On the main form we add UserControl1 the necessary number of times.
private void testCheckBoxes(object obj)
{
if (obj is UserControl1 control)
{
string text = control.TextForAdd;
// .....
}
}
private void button1_Click(object sender, EventArgs e)
{
foreach (Control control in this.LeftPanel.Controls)
{
if (control as UserControl1 != null)
{
if (control.Visible == true )
{
testCheckBoxes(control);
}
}
}
}
How can I Set the special property of multiple controls to the same value?
For example set the visible property of all labels in the form to true.
I use this code but labels appear to have null values but they have values.
protected void Page_Load(object sender, EventArgs e)
{
foreach ( Label lbl in this.Controls.OfType<Label>()) {
if (lbl == null) continue;
lbl.Visible = false;
}
}
I should mention that I use master page.But I don't want to set the properties of my nested master pages. I want to set the properties of just current ASP page.
You may have some controls within others, so you need to call it recusrively....Here's a similat method I use..............
Notice at the end, I call it from within itself if the Control in question has controls of its' own....
Hope this helps.....
private void ClearControls(ControlCollection controlCollection, bool ignoreddlNewOrExisting = false)
{
foreach (Control control in controlCollection)
{
if (ignoreddlNewOrExisting)
{
if (control.ID != null)
{
if (control.ID.ToUpper() == "DDLNEWOREXISTING")
{
continue;
}
}
}
if (control is TextBox)
{
((TextBox)control).Text = "";
((TextBox)control).Font.Size = 10;
}
if (control is DropDownList)
{
((DropDownList)control).SelectedIndex = 0;
((DropDownList)control).Font.Size = 10;
}
if (control is CheckBox)
{
((CheckBox)control).Checked = false;
}
//A bit of recursion
if (control.Controls != null)
{
this.ClearControls(control.Controls, ignoreddlNewOrExisting);
}
}
}
Note that you can use following to avoid this ugly type check.:
foreach(Label lbl in this.Controls.OfType<Label>())
lbl.Visible= false;
But neither your nor my approach will enumerate all controls recursively. Only the controls which are on top of the page. So you won't find labels in nested controls(f.e. in a GridView) or which are in the MasterPage. Therefore you need a recursive method.
You could use this handy extension method:
public static class ControlExtensions
{
public static IEnumerable<Control> GetControlsRecursively(this Control parent)
{
foreach (Control c in parent.Controls)
{
yield return c;
if (c.HasControls())
{
foreach (Control control in c.GetControlsRecursively())
{
yield return control;
}
}
}
}
}
Then this readable code should hide all labels on the page and in the MasterPage:
var allLabels = this.GetControlsRecursively()
.Concat(this.Master.GetControlsRecursively())
.OfType<Label>();
foreach (Label label in allLabels)
label.Visible = false;
protected void Page_Load(object sender, EventArgs e)
{
SetAllLabelValue(this.Controls);
}
private void SetAllLabelValue(ControlCollection controls)
{
foreach (Control item in controls)
{
if (item.HasControls())
{
SetAllLabelValue(item.Controls);
}
Label lb = item as Label;
if (lb != null)
{
lb.Visible = false;
}
}
}
I have created a custom web server control that will have a bool property 'RenderAsLabel' so that I can convert textboxes to labels, for Read-only forms. I was wondering if there is any reason why this code should not be safe, or work as intended. Upon initial testing it seems fine, but I just want to make sure I'm not doing something that will end up causing issues.
namespace OrmControlLibrary
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:OrmTextBox ID='' runat=server ></{0}:OrmTextBox>")]
public class OrmTextBox : TextBox
{
private Label lbl;
public virtual bool RenderAsLabel
{
get
{
if (ViewState["OrmTextBox"] == null)
{
return false;
}
else
{
return (bool)ViewState["OrmTextBox"];
}
}
set
{
ViewState["OrmTextBox"] = value;
}
}
protected override void Render(HtmlTextWriter w)
{
if (RenderAsLabel)
{
SetLabelProperties();
lbl.RenderControl(w);
}
else
{
base.Render(w);
}
}
private void SetLabelProperties()
{
lbl = new Label();
lbl.ID = this.ID;
lbl.CssClass = this.CssClass;
lbl.Text = this.Text;
}
}
}
Not found anything that directly answers my problem, so hopefully someone can shed some light on it.
I have two Composite Controls, lets call them BudgetTable and BudgetTableItem, where BudgetTable contains a list of BudgetTableItem.
So far everything works so long as I add new RowItems in the HTML View - when I add one programmatically it appears, but doesn't survive postback.
I can only assume I'm doing something boneheaded with ViewState, and would appreciate any pointers!
Thanks in advance.
The HTML:
<hea:BudgetTable runat="server" ID="btTest" MaximumFundingAvailable="7000" CssClass="bob">
<Items>
<hea:BudgetTableItem runat="server" Description="Test1" />
<hea:BudgetTableItem runat="server" Description="Test2" />
<hea:BudgetTableItem runat="server" Description="Test3" />
</Items>
</hea:BudgetTable>
The code behind:
[PersistenceMode(PersistenceMode.InnerProperty)]
[ParseChildren(true)]
public class BudgetTableItem : CompositeControl {
private TextBox _description = new TextBox();
private TextBox _cost = new TextBox();
private CheckBox _heaFunded = new CheckBox();
/*public delegate void AddRow();
public delegate void RemoveRow(BudgetTableItem item);
public event AddRow AddNewRow;
public event RemoveRow RemoveNewRow;*/
public string ItemName {
get {
var viewstate = ViewState["ItemName"];
return (viewstate is string) ? (string)viewstate : "default";
}
set {
ViewState["ItemName"] = value;
}
}
public bool ShowRemoveRow {
get {
var viewstate = ViewState["ShowRemoveRow"];
return (viewstate != null && viewstate is bool) ? (bool)viewstate : false;
}
set {
ViewState["ShowRemoveRow"] = value;
}
}
public bool ShowAddRow {
get {
var viewstate = ViewState["ShowAddRow"];
return (viewstate != null && viewstate is bool) ? (bool)viewstate : false;
}
set {
ViewState["ShowAddRow"] = value;
}
}
public string Description {
get {
return _description.Text;
}
set {
_description.Text = value;
}
}
public decimal Cost {
get {
decimal cost =0;
decimal.TryParse(_cost.Text, out cost);
return cost;
}
set {
_cost.Text = value.ToString();
}
}
public bool HeaFunded {
get {
return _heaFunded.Checked;
}
set {
_heaFunded.Checked = value;
}
}
protected override void CreateChildControls() {
Controls.Clear();
HtmlTableCell tableCell1 = new HtmlTableCell();
HtmlTableCell tableCell2 = new HtmlTableCell();
HtmlTableCell tableCell3 = new HtmlTableCell();
HtmlTableCell tableCell4 = new HtmlTableCell();
tableCell1.Attributes.Add("class", "col1");
tableCell2.Attributes.Add("class", "col2");
tableCell3.Attributes.Add("class", "col3");
tableCell4.Attributes.Add("class", "col4");
tableCell1.Controls.Add(_description);
tableCell2.Controls.Add(_cost);
tableCell3.Controls.Add(_heaFunded);
/*if (ShowAddRow || ShowRemoveRow) {
Button addNewButton = new Button();
addNewButton.Text = (ShowAddRow) ? "Add Row" : "Remove";
if (ShowAddRow) {
addNewButton.Click += new EventHandler(addNewButton_Click);
}
if (ShowRemoveRow) {
addNewButton.Click += new EventHandler(removeButton_Click);
}
tableCell4.Controls.Add(addNewButton);
}
else{*/
tableCell4.InnerHtml = " ";
//}
Controls.Add(tableCell1);
Controls.Add(tableCell2);
Controls.Add(tableCell3);
Controls.Add(tableCell4);
}
/*void addNewButton_Click(object sender, EventArgs e) {
if (AddNewRow != null) {
AddNewRow();
}
}*/
/*void removeButton_Click(object sender, EventArgs e) {
if (RemoveNewRow != null) {
RemoveNewRow(this);
}
}*/
protected override void RecreateChildControls() {
EnsureChildControls();
}
public override void RenderBeginTag(HtmlTextWriter writer) {
writer.Write("<tr>");
}
public override void RenderEndTag(HtmlTextWriter writer) {
writer.Write("</tr>");
}
}
Controls, custom or otherwise that require a ViewState and wish to receive events should be created in Init.
Http is stateless. Your entire page with all its controls is recreated on every postback. Controls that you add in the design view, are added to your designer.cs file, and created for you. When you add controls yourself, you must write code to recreate the controls on every PostBack that occurs later.
You can use the session to remember which controls were added by code and add them on later PostBacks.
I've created a custom WebControl that implements a simple message box that can display at the top of a web page. Similar to how YouTube displays messages on their pages. My problem is passing the Click event from any button I add to the box down to the ASPX page.
Below is the code for the WebControl. I think I have handling the click events right, but when I add this code to my page, the click event never gets called, although Page_Load does.
Here's the code in the APSX page:
<rt:ConfirmationBox ID="ConfirmationBox1" runat="server" BoxType="Info" BoxButtons="OkayCancel" OnOkayClicked="ConfirmationBoxOkayClicked"
Text="Click OK to close." />
Here's the code in the code behind page:
protected void ConfirmationBoxOkayClicked(object sender, EventArgs e)
{
ConfirmationBox1.BoxButtons = ConfirmationBoxButtons.None;
ConfirmationBox1.BoxType = ConfirmationBoxType.Success;
ConfirmationBox1.Text = "You clicked OK!";
}
Here's the WebControl code:
public enum ConfirmationBoxType
{
Hidden,
Success,
Warn,
Error,
Info
}
public enum ConfirmationBoxButtons
{
None,
Okay,
Cancel,
OkayCancel
}
[DefaultProperty("Text")]
[ToolboxData("<{0}:ConfirmationBox ID=\"ConfirmationBox1\" runat=server></{0}:ConfirmationBox>")]
public class ConfirmationBox : WebControl
{
private static readonly ILog Log = LogManager.GetLogger(typeof(ConfirmationBox));
private Button _okayButton;
private Button _cancelButton;
public event EventHandler OkayClicked;
public event EventHandler CancelClicked;
public virtual void OnOkayClicked(object sender, EventArgs eventArgs)
{
if (OkayClicked != null)
OkayClicked(sender, eventArgs);
}
public virtual void OnCancelClicked(object sender, EventArgs eventArgs)
{
if (CancelClicked != null)
CancelClicked(sender, eventArgs);
}
protected override void OnPreRender(EventArgs e)
{
_okayButton = new Button {ID = "ConfirmBoxOkayButton", CssClass = "button", Text = "OK"};
_okayButton.Click += new EventHandler(OnOkayClicked);
_cancelButton = new Button {ID = "ConfirmBoxCancelButton", CssClass = "button", Text = "Cancel"};
_cancelButton.Click += new EventHandler(OnCancelClicked);
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text
{
get
{
var s = (String)ViewState["Text"];
return (s ?? String.Empty);
}
set
{
ViewState["Text"] = value;
}
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("Hidden")]
public ConfirmationBoxType BoxType
{
get
{
return (ConfirmationBoxType)ViewState["BoxType"];
}
set
{
ViewState["BoxType"] = value;
}
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("None")]
public ConfirmationBoxButtons BoxButtons
{
get
{
return (ConfirmationBoxButtons)ViewState["BoxButtons"];
}
set
{
ViewState["BoxButtons"] = value;
}
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Id, "alerts");
base.AddAttributesToRender(writer);
}
protected override void RenderContents(HtmlTextWriter writer)
{
if (Site != null && Site.DesignMode)
{
writer.Write("[" + ID + "]");
}
else
{
if (BoxType == ConfirmationBoxType.Hidden)
return;
var theme = HttpContext.Current.Profile["UserTheme"].ToString();
writer.AddAttribute(HtmlTextWriterAttribute.Id, "confirmBox");
writer.AddAttribute(HtmlTextWriterAttribute.Class, "rt-alert " + RenderBoxType());
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddAttribute(HtmlTextWriterAttribute.Src, string.Format("{0}/{1}/pixel.gif", ResolveUrl("~/App_Themes"), (string.IsNullOrEmpty(theme)) ? "Default" : theme));
writer.AddAttribute(HtmlTextWriterAttribute.Class, "icon");
writer.AddAttribute(HtmlTextWriterAttribute.Alt, "Alert icon");
writer.RenderBeginTag(HtmlTextWriterTag.Img);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "rt-alert-content");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.Write(Text);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Type, "button");
writer.AddAttribute(HtmlTextWriterAttribute.Class, "close");
writer.AddAttribute(HtmlTextWriterAttribute.Onclick, "$(\"#alerts\").hide()");
writer.RenderBeginTag(HtmlTextWriterTag.Button);
writer.Write("close");
writer.RenderEndTag();
if (BoxButtons != ConfirmationBoxButtons.None)
{
writer.AddAttribute(HtmlTextWriterAttribute.Class, "rt-alert-buttons");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
if (BoxButtons == ConfirmationBoxButtons.Okay || BoxButtons == ConfirmationBoxButtons.OkayCancel)
_okayButton.RenderControl(writer);
if (BoxButtons == ConfirmationBoxButtons.Cancel || BoxButtons == ConfirmationBoxButtons.OkayCancel)
_cancelButton.RenderControl(writer);
writer.RenderEndTag();
}
writer.RenderEndTag();
}
}
private string RenderBoxType()
{
switch (BoxType)
{
case ConfirmationBoxType.Success:
return "rt-alert-success";
case ConfirmationBoxType.Warn:
return "rt-alert-warn";
case ConfirmationBoxType.Error:
return "rt-alert-error";
case ConfirmationBoxType.Info:
return "rt-alert-info";
}
return string.Empty;
}
}
Create a separate method for your custom event handler, like this:
protected virtual void OnOkayClicked(EventArgs e)
{
if (OkayClicked!= null)
OkayClicked(this, e);
}
Change the name of the button click event and make it protected, like this:
protected void OkayButton_Click(object sender, EventArgs e)
{
//call your event handler method
this.OnOkayClicked(EventArgs.Empty);
}
Test this out, and see if it makes a difference.