Set the special property of multiple controls to the same value - c#

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;
}
}
}

Related

Can't locate control from string

I have a custom extension method that (is supposed to) find a control via a string, and perform a click to that control. I've set up a break point and it nevers into the if (c is ToolStripMenuItem) Anyone have any idea where I'm going wrong? This is on WinForms.
private void PerformClickfromString()
{
string item = File.ReadAllText(#"C:\controltest.txt");
foreach (var c in this.Controls)
{
if (c is ToolStripMenuItem)
{
var x = (ToolStripMenuItem)c;
if (x.Name == item)
{
x.PerformClick();
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
PerformClickfromString();
}
Any help is appreciated.
To find all nested items you need a recursive search. Here is an example; it collects all items in a List<ToolStripMenuItem> and the checks for the searched name. I have added that string to the signature of your call..:
private void PerformClickfromString(string s)
{
foreach (var c in this.Controls)
{
List<ToolStripMenuItem> items = new List<ToolStripMenuItem>();
if (c is MenuStrip)
{
foreach (ToolStripMenuItem tsItem in ((MenuStrip)c).Items)
{
GetAllMenuItems(items, tsItem);
}
}
ToolStripMenuItem found = items.Find(x => x.Name == s);
if (found != null) found.PerformClick();
}
}
void GetAllMenuItems(List<ToolStripMenuItem> items, ToolStripMenuItem menu)
{
items.Add(menu);
foreach(ToolStripMenuItem m in menu.DropDownItems)
GetAllMenuItems(items, m);
}
The ToolStripMenuItem is not considered a control, you must instead use its container
if(c is MenuStrip)
{
foreach(ToolStripMenuItem tsItem in ((MenuStrip)c).Items)
{
if (tsItem.Name == item)
{
tsItem.PerformClick();
}
}
}

Check more than one checkbox upon clicking a button c#

I have for example:
Checkbox1.IsChecked = true;
Checkbox2.IsChecked = true;
Checkbox3.IsChecked = true;
I have this 32 times. Is there a way to have concat string? For example:
i = 1
while i < 32:
("Checkbox"+ (i)).IsChecked = true;
i++
Thanks
While you cannot do exactly what you intend, you can check or uncheck all checkboxes that are in a given container. For example, let's say you have a Panel that contains a number of checkboxes, called pnlChecks. You could do something like
foreach (var chkBox in pnlChecks.Controls.OfType<CheckBox>())
{
chkBox.IsChecked = true;
}
There are multiple methods to achieve this.
Add all of them to a generic List<> and iterate through them like the for you mentioned.
Use reflection and get the checkbox controls and set their value.
Sample WinForms Code
private List<CheckBox> checkboxes = new List<CheckBox>();
public Form1()
{
InitializeComponent();
FillCheckboxes();
}
private void CheckAll()
{
foreach (var chk in checkboxes)
{
chk.Checked = true;
}
}
private void FillCheckboxes()
{
foreach (Control c in this.Controls)
{
if (c is CheckBox)
{
checkboxes.Add(c as CheckBox);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
CheckAll();
}
Sample WPF Code
private List<CheckBox> checkboxes = new List<CheckBox>();
public Window1()
{
InitializeComponent();
checkboxes = FindVisualChildren<CheckBox>(main).ToList();
CheckAll();
}
private void CheckAll()
{
foreach (var chk in checkboxes)
{
chk.IsChecked = true;
}
}
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
Important Note
For WPF the suggested method is to use data binding instead of iterating through controls and manually checking/unchecking them. Just bind the IsChecked property to the desired value and change it. You can find more info regarding this on numerous articles on the Internet.

Textchanges only visible after postback

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?

give same property to all textbox controls

how to give same property to all textboxes present in the same form.
foreach (var textbox in this.Controls.OfType<TextBox>())
{
textbox.ContextMenu = new ContextMenu();
}
The above code works only if the textboxes are not in nested format.
In my project I have multiple tabpages in tabcontrol. so i cant implement the above code. but i can implement the below code:
foreach (TextBox textbox in this.Controls.OfType<TabControl>().SelectMany(tc => tc.Controls.OfType<TabPage>().SelectMany(page => page.Controls.OfType<TextBox>())))
{
textbox.ContextMenu = new ContextMenu();
}
foreach (var textbox in this.tabCarInsurance.Controls.OfType<TextBox>())
{
textbox.ContextMenu = new ContextMenu();
}
foreach (var textbox in this.tabHomeLoans.Controls.OfType<TextBox>())
{
textbox.ContextMenu = new ContextMenu();
}
foreach (var textbox in this.tabRetirement.Controls.OfType<TextBox>())
{
textbox.ContextMenu = new ContextMenu();
}
Here I am implementing for each tabControl. which still i dont like (because I have more tab pages to take care of). Is there anyway to reduce the above code.
I tried the below code: (not working)
foreach (var textbox in this.Controls.OfType<TabControl>().OfType<TextBox>())
{
textbox.ContextMenu = new ContextMenu();
}
I got the above code knowledge from my previous question.
Please Help
Thanks in Advance.
private void SetProperty(Control ctr)
{
foreach(Control control in ctr.Controls)
{
if (control is TextBox)
{
control.ContextMenu = new ContextMenu();
}
else
{
if (control.HasChildren)
{
SetProperty(control);
}
}
}
}
How about an extension method to do it, called from your tabcontrol container...
public static class ControlExtensions
{
public static void SetContextMenuOnChildTextBoxes(this Control control)
{
if (control is TextBox)
{
control.ContextMenu = new ContextMenu();
}
if (control.Controls != null)
{
foreach (Control controlChild in control.Controls)
{
controlChild.SetContextMenuOnChildTextBoxes();
}
}
}
}
This could be put in a common area of code so that it could be called from any parents that wanted this functionality.
Just use the recursion to go through all controls subcollections:
void SetControl(ContextMenu menu, Control control)
{
if (control is TextBox)
control.ContextMenu = menu;
else
{
foreach (Control c in control.Controls)
SetControl(menu, c);
}
}
It will find all the textboxes and set one and the same context menu to all of them.
You mal call it,say, from form's OnLoad event handler. While it's assumed that you have yourContextMenu defined for the form.
private void Form1_Load(object sender, EventArgs e)
{
SetControl(yourContextMenu, this);
}
Try:
private void CtxMenu(Control parent)
{
foreach (Control child in parent.Controls)
{
if (child is TextBox)
{
(child as TextBox).ContextMenu = new ContextMenu();
}
}

How to get TabPage on which a user control data type resides

I'm building a custom data type using the user control wrappper method. Within it I am adding the existing TinyMCE data type. The problem is that I need to find a way to dynamically get a hold of the current TabPage on which the data type resides so that I can add the TinyMCE buttons to the menu. This is what I have currently (the TabPage is hardcoded):
Using statements:
using umbraco.cms.businesslogic.datatype;
using umbraco.editorControls.tinyMCE3;
using umbraco.uicontrols;
OnInit method:
private TinyMCE _tinymce = null;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.ID = "crte";
DataTypeDefinition d = DataTypeDefinition.GetDataTypeDefinition(-87);
_tinymce = d.DataType.DataEditor as TinyMCE;
ConditionalRTEControls.Controls.Add(_tinymce);
TabView tabView = Page.FindControl("TabView1", true) as TabView;
TabPage tabPage = tabView.Controls[0] as TabPage;
tabPage.Menu.InsertSplitter();
tabPage.Menu.NewElement("div", "umbTinymceMenu_" + _tinymce.ClientID, "tinymceMenuBar", 0);
}
User control:
<asp:PlaceHolder ID="ConditionalRTEControls" runat="server" />
Note: Page.FindControl is using a custom extension method that recursively finds the control.
I'd love if there was a way to access the TabPage via the Umbraco API, but, after working on this for the past several hours, the only way I could get the tab was by traversing the parent controls until I came to the tab.
Code:
private TinyMCE _tinymce = null;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.ID = "crte";
DataTypeDefinition d = DataTypeDefinition.GetDataTypeDefinition(-87);
_tinymce = d.DataType.DataEditor as TinyMCE;
ConditionalRTEControls.Controls.Add(_tinymce);
}
protected void Page_Load(object sender, EventArgs e)
{
TabView tabView = Page.FindControl("TabView1", true) as TabView;
TabPage tabPage = GetCurrentTab(ConditionalRTEControls, tabView);
tabPage.Menu.NewElement("div", "umbTinymceMenu_" + _tinymce.ClientID, "tinymceMenuBar", 0);
}
private TabPage GetCurrentTab(Control control, TabView tabView)
{
return control.FindAncestor(c => tabView.Controls.Cast<Control>().Any(t => t.ID == c.ID)) as TabPage;
}
Extension Methods:
public static class Extensions
{
public static Control FindControl(this Page page, string id, bool recursive)
{
return ((Control)page).FindControl(id, recursive);
}
public static Control FindControl(this Control control, string id, bool recursive)
{
if (recursive)
{
if (control.ID == id)
return control;
foreach (Control ctl in control.Controls)
{
Control found = ctl.FindControl(id, recursive);
if (found != null)
return found;
}
return null;
}
else
{
return control.FindControl(id);
}
}
public static Control FindAncestor(this Control control, Func<Control, bool> predicate)
{
if (predicate(control))
return control;
if (control.Parent != null)
return control.Parent.FindAncestor(predicate);
return null;
}
}

Categories

Resources