Radio Button Check Control With Tab Pages - c#

I have a number of different tabs and within the tabs i have some radio buttons. I only want one radio button at a time within the tab pages to be selected. I have the following code
private void RadioButtonCheckedChanged(object sender, EventArgs e)
{
TabControl.TabPageCollection pages = tabControl1.TabPages;
var rdoButtonName = sender as RadioButton;
foreach (TabPage page in pages)
{
foreach (Control item in page.Controls)
{
if (item is RadioButton)
{
if (rdoButtonName.Name == item.Name)
{
rdoButtonName.Checked = true;
}
else
{
rdoButtonName.Checked = false;
}
}
}
}
}
When i go to click on the radio buttons on the first tab page it does not allow me to change their checked status but it does on the other pages. Can anyone see anything wrong with the above code?

I see that you set Cheked value to the sender and not to other radio buttons...
private void RadioButtonCheckedChanged(object sender, EventArgs e)
{
TabControl.TabPageCollection pages = tabControl1.TabPages;
var rdoButtonName = sender as RadioButton;
foreach (TabPage page in pages)
{
foreach (Control item in page.Controls)
{
if (item is RadioButton)
{
if (item.Name != rdoButtonName.Name)
{
item.Checked = false;
}
}
}
}
}

I think (better debug and check) that your problem is that each time you change one of your RadioButton state it will call this function over again and will make the unexpected results.
To fix that I would detach and reattach your event handler before changing the Checked state, like this:
private void RadioButtonCheckedChanged(object sender, EventArgs e)
{
TabControl.TabPageCollection pages = tabControl1.TabPages;
var rdoButtonName = sender as RadioButton;
foreach (TabPage page in pages)
{
foreach (Control item in page.Controls)
{
if (item is RadioButton)
{
rdoButtonName.CheckedChanged -= new System.EventHandler(this.RadioButtonCheckedChanged);
if (rdoButtonName.Name == item.Name)
{
rdoButtonName.Checked = true;
}
else
{
rdoButtonName.Checked = false;
}
rdoButtonName.CheckedChanged += new System.EventHandler(this.RadioButtonCheckedChanged);
}
}
}
}

The problem is, that "CheckedChanged"-event can't be used in this kind of situation, and that is where the problem lies. The key is to use another event - "Click":
private void radioButton_Click(object sender, EventArgs e)
{
foreach (TabPage page in tabControl1.TabPages)
{
foreach (RadioButton radioButton in page.Controls)
{
if (radioButton != (RadioButton)sender) { radioButton.Checked = false; }
}
}
}
Change your RadioButtons to use this method in the "Click"-event and it'll work. I tested it myself.

Related

When i'm checking if site uploaded complete in webBrowser DocumentCompleted it's all the in Interactive state what else can i do?

In constructor
webBrowser2.ScriptErrorsSuppressed = true;
webBrowser2.Navigate("http://www.tapuz.co.il/forums/forumpage/393");
Then in DocumentCompleted
void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
while (webBrowser2.ReadyState != WebBrowserReadyState.Complete)
{
return;
}
HtmlElementCollection items = this.webBrowser2.Document.GetElementsByTagName("span");
foreach (HtmlElement item in items)
{
if (item.GetAttribute("className") == "addMessage")
{
item.InvokeMember("click");
}
}
}
I tried with the while loop and without.
If without the while loop for some reason it's keep loading the page over and over again every 2-3 seconds.
With the loop i see all the time that the webBrowser2.ReadyState is Interactive all the time.
Also this site is making automatic refresh. But it's never get to the "click"
This is what i see when i make Inspect Element on the addMessage button:
<div id="SecondLineMenu-sticky-wrapper" class="sticky-wrapper" style="height: 60px;"><div class="SecondLineMenu" id="SecondLineMenu" style="width: 1000px;">
<span class="addMessage" onclick="location='http://www.tapuz.co.il/forums/addmsg/393/טבע_ומזג_אוויר/מזג_האוויר'"> | הוספת הודעה</span>
I want to click the addMessage button but it's never get there.
I found this working:
bool clicked = false;
private void webBrowser2_DocumentCompleted_1(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (this.webBrowser2.Document != null)
{
if (clicked == false)
{
HtmlElementCollection items = webBrowser2.Document.GetElementsByTagName("span");
foreach (HtmlElement item in items)
{
if (item.GetAttribute("className") == "addMessage")
{
item.InvokeMember("click");
clicked = true;
break;
}
}
}
}
}
Should i add this as solution ?
bool clicked = false;
private void webBrowser2_DocumentCompleted_1(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (this.webBrowser2.Document != null)
{
if (clicked == false)
{
HtmlElementCollection items = webBrowser2.Document.GetElementsByTagName("span");
foreach (HtmlElement item in items)
{
if (item.GetAttribute("className") == "addMessage")
{
item.InvokeMember("click");
clicked = true;
break;
}
}
}
}
}

Search function for controls at run time

I have a tab control where I can add custom controls made from a button and a label underneath. I want to add a search function to my project so that when a user type a name of a control, it will show all controls where the name (label) starts with the letters typed. Also typing in a textbox will do the job.. Is there an easy way to do this?
You can search controls within parent control collection:
foreach(Control c in ParentControl.Controls)
{
if(c.Name == "label1")
{
//add to your list
}
}
You can also check using StartsWith("stringVal")
if(c.Name.StartsWith("l"))
{
//add to your list
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
foreach (Control control in this.Controls)
{
// Skip, if the control is the used TextBox
if (control == textBox1) { continue; }
// Show all controls where name starts with inputed string
// (use ToLower(), so casing doesnt matter)
if (control.Name.ToLower().StartsWith(textBox1.Text.Trim().ToLower()))
{
control.Visible = true;
}
// Hide objects that doesn't match
else { control.Visible = false; }
}
}
This toggles the controls' visibility, and hide's all items, that doesn't match the given input. Also casing doesn't matter.
Done when adding the text to search in a textbox.
private void textBox1_TextChanged(object sender, EventArgs e)
{
foreach (Control c in fl_panel.Controls)
{
if (c.Name.ToUpper().StartsWith(textBox1.Text.ToUpper().ToString()) && textBox1.Text != "")
{
Control[] ctrls = fl_panel.Controls.Find(textBox1.Text.ToString(), true);
c.Visible = true; // to restore previous matches if I delete some text
}
else if(textBox1.Text == "")
{
c.Visible = true;
}
else
{
c.Visible = false;
}
}
}
you can try this to find the controls that matches a text typed in the textbox, after that you can do whatever you want with it.
private void textBox1_TextChanged(object sender, EventArgs e)
{
var controlMatchesCriteria = from c in this.Controls.OfType<TextBox>()
where c.Name == textBox1.Text
select c;
}

Reset all the items in a form

I was wondering, is there a way I can reset all the checkboxes, textboxes, numerics and other controls back to the default values without writing code for every control individually? This is the code I've tried, but doesn't seem to work:
for (int i = 0; i < this.Controls.Count; i++)
{
this.Controls[i].ResetText();
}
EDIT:
I've fixed it by manually setting the control values, sorry for all the trouble >.<.
Do as below create class and call it like this
Check : Reset all Controls (Textbox, ComboBox, CheckBox, ListBox) in a Windows Form using C#
private void button1_Click(object sender, EventArgs e)
{
Utilities.ResetAllControls(this);
}
public class Utilities
{
public static void ResetAllControls(Control form)
{
foreach (Control control in form.Controls)
{
if (control is TextBox)
{
TextBox textBox = (TextBox)control;
textBox.Text = null;
}
if (control is ComboBox)
{
ComboBox comboBox = (ComboBox)control;
if (comboBox.Items.Count > 0)
comboBox.SelectedIndex = 0;
}
if (control is CheckBox)
{
CheckBox checkBox = (CheckBox)control;
checkBox.Checked = false;
}
if (control is ListBox)
{
ListBox listBox = (ListBox)control;
listBox.ClearSelected();
}
}
}
}
You can create the form again and dispose the old one.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnReset_Click(object sender, EventArgs e)
{
Form1 NewForm = new Form1();
NewForm.Show();
this.Dispose(false);
}
}
foreach (Control field in container.Controls)
{
if (field is TextBox)
((TextBox)field).Clear();
else if (field is ComboBox)
((ComboBox)field).SelectedIndex=0;
else
dgView.DataSource = null;
ClearAllText(field);
}
Additional-> To clear the Child Controls
The below function would clear the nested(Child) controls also, wrap up in a class.
public static void ClearControl(Control control)
{
if (control is TextBox)
{
TextBox txtbox = (TextBox)control;
txtbox.Text = string.Empty;
}
else if (control is CheckBox)
{
CheckBox chkbox = (CheckBox)control;
chkbox.Checked = false;
}
else if (control is RadioButton)
{
RadioButton rdbtn = (RadioButton)control;
rdbtn.Checked = false;
}
else if (control is DateTimePicker)
{
DateTimePicker dtp = (DateTimePicker)control;
dtp.Value = DateTime.Now;
}
else if (control is ComboBox)
{
ComboBox cmb = (ComboBox)control;
if (cmb.DataSource != null)
{
cmb.SelectedItem = string.Empty;
cmb.SelectedValue = 0;
}
}
ClearErrors(control);
// repeat for combobox, listbox, checkbox and any other controls you want to clear
if (control.HasChildren)
{
foreach (Control child in control.Controls)
{
ClearControl(child);
}
}
}
If you have some panels or groupboxes reset fields should be recursive.
public class Utilities
{
public static void ResetAllControls(Control form)
{
foreach (Control control in form.Controls)
{
RecursiveResetForm(control);
}
}
private void RecursiveResetForm(Control control)
{
if (control.HasChildren)
{
foreach (Control subControl in control.Controls)
{
RecursiveResetForm(subControl);
}
}
switch (control.GetType().Name)
{
case "TextBox":
TextBox textBox = (TextBox)control;
textBox.Text = null;
break;
case "ComboBox":
ComboBox comboBox = (ComboBox)control;
if (comboBox.Items.Count > 0)
comboBox.SelectedIndex = 0;
break;
case "CheckBox":
CheckBox checkBox = (CheckBox)control;
checkBox.Checked = false;
break;
case "ListBox":
ListBox listBox = (ListBox)control;
listBox.ClearSelected();
break;
case "NumericUpDown":
NumericUpDown numericUpDown = (NumericUpDown)control;
numericUpDown.Value = 0;
break;
}
}
}
You can reset all controls of a certain type. Something like
foreach(TextBox tb in this.Controls.OfType<TextBox>().ToArray())
{
tb.Clear();
}
But you can't reset all controls at once
Quick answer, maybe it'll help:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.ShowDialog();
while (f2.DialogResult == DialogResult.Retry)
{
f2 = new Form2();
f2.ShowDialog();
}
}
and in Form2 (The 'settings' Form):
private void button1_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
Close();
}
private void button2_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Retry;
Close();
}
I recently had to do this for Textboxes and Checkboxes but using JavaScript ...
How to reset textbox and checkbox controls in an ASP.net document
Here is the code ...
<script src="http://code.jquery.com/jquery-1.7.1.js" type="text/javascript"></script>
<script type="text/javascript">
function ResetForm() {
//get the all the Input type elements in the document
var AllInputsElements = document.getElementsByTagName('input');
var TotalInputs = AllInputsElements.length;
//we have to find the checkboxes and uncheck them
//note: <asp:checkbox renders to <input type="checkbox" after compiling, which is why we use 'input' above
for(var i=0;i< TotalInputs ; i++ )
{
if(AllInputsElements[i].type =='checkbox')
{
AllInputsElements[i].checked = false;
}
}
//reset all textbox controls
$('input[type=text], textarea').val('');
Page_ClientValidateReset();
return false;
}
//This function resets all the validation controls so that they don't "fire" up
//during a post-back.
function Page_ClientValidateReset() {
if (typeof (Page_Validators) != "undefined") {
for (var i = 0; i < Page_Validators.length; i++) {
var validator = Page_Validators[i];
validator.isvalid = true;
ValidatorUpdateDisplay(validator);
}
}
}
</script>
And call it with a button or any other method ...
<asp:button id="btnRESET" runat="server" onclientclick="return ResetForm();" text="RESET" width="100px"></asp:button>
If you don't use ValidationControls on your website, just remove all the code refering to it above and the call Page_ClientValidateReset();
I am sure you can expand it for any other control using the DOM. And since there is no post to the server, it's faster and no "flashing" either.
function setToggleInputsinPnl(pnlName) {
var domCount = pnlName.length;
for (var i = 0; i < domCount; i++) {
if (pnlName[i].type == 'text') {
pnlName[i].value = '';
} else if (pnlName[i].type == 'select-one') {
pnlName[i].value = '';
}
}
}
There is a very effective way to use to clear or reset Windows Form C# controls like TextBox, ComboBox, RadioButton, CheckBox, DateTimePicker etc.
private void btnClear_Click(object sender, EventArgs e)
{
Utilities.ClearAllControls(this);
}
internal class Utilities
{
internal static void ClearAllControls(Control control)
{
foreach (Control c in control.Controls)
{
if (c is TextBox)
{
((TextBox)c).Clear();
}
else if (c is ComboBox)
{
((ComboBox)c).SelectedIndex = -1;
}
else if (c is RadioButton)
{
((RadioButton)c).Checked = false;
}
else if (c is CheckBox)
{
((CheckBox)c).Checked = false;
}
else if (c is DateTimePicker)
{
((DateTimePicker)c).Value = DateTime.Now; // or null
}
}
}
}
To accomplish this with overall user experience in c# we can use one statement to clear them. Pretty straight forward so far, above is the code.

Dynamically filtering a menu (ContextMenuStrip) in C# without recreating the menu?

Is this possible?
I plan to have 10 menu items where these are going to have sub-menu items (1 level deep only). I want to be able to filter them when the user types into my TextBox control. I know I can filter items upon opening the menu for the first time, but I want to be able to continually filter it as the user types and hide categories on the fly when the category menu item has no subitems applicable for the current filter (by name filtering).
Any ideas?
I added a context menu strip (menuStrip1). To this I added the following:
File
Exit
Edit
Copy
Paste
Further Down
Help
Arghhhh!
I then added a text box (FilterMenuText), and, on the OnTextChanged event, do the following:
private void FilterMenuText_TextChanged(object sender, EventArgs e)
{
foreach (ToolStripMenuItem menuItem in menuStrip1.Items)
{
if (menuItem.DropDownItems.Count > 0)
{
bool matchFound = false;
foreach (ToolStripMenuItem childMenuItem in menuItem.DropDownItems)
{
if (childMenuItem.Text.ToUpper().Contains(FilterMenuText.Text.ToUpper()))
{
matchFound = true;
break;
}
}
menuItem.Visible = matchFound;
}
}
}
This will hide and show the top level MenuItems as appropriate based on the content of the child menu items. If your menu has more than one level of drop down, put the foreach into a recursive function, like:
private void FilterMenuText_TextChanged(object sender, EventArgs e)
{
foreach (ToolStripMenuItem menuItem in menuStrip1.Items)
{
menuItem.Visible = MenuItemHasChildWithName(menuItem, FilterMenuText.Text);
}
}
private bool MenuItemHasChildWithName(ToolStripMenuItem menuItem, string name)
{
if (!menuItem.HasDropDownItems)
{
return false;
}
bool matchFound = false;
foreach (ToolStripMenuItem childMenuItem in menuItem.DropDownItems)
{
if (childMenuItem.Text.ToUpper().Contains(name.ToUpper()))
{
matchFound = true;
break;
}
if (childMenuItem.HasDropDownItems)
{
matchFound = MenuItemHasChildWithName(childMenuItem, name);
if(matchFound) { break; }
}
}
return matchFound;
}
This is what I used for conditionaly showing menu items on a context menu. If you use the same menu and don't want to show it, you merely set each item in the same loop to true;
private void dgViewData_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
if (dgViewData.HitTest(e.X, e.Y).Type != DataGridViewHitTestType.ColumnHeader)
{
foreach (ToolStripMenuItem menuItem in conMicImport.Items)
{
menuItem.Visible = menuItem.Text.ToString().Contains("Add") == true ? false : true;
}
conMicImport.Show(dgViewData, e.Location);
ctxtDG = dgViewData;
}
}
}
Set the toolstrip object's Visible property to false when you don't want it to appear.
for example purposes I have done this using a web forms application
foreach (Control c in Page.Form.Controls)
{
//Response.Write("WORD2" + c.GetType());
if (c is Panel)
{
foreach (Control p in c.Controls)
{
if (p is CheckBoxList)
{
foreach (ListItem li in ((CheckBoxList)p).Items)
{
li.Selected = false;
}
}
}
}
}

Set Statusbar Text on Mouse Hover - Works for controls but not MenuItems

I devised the following code for displaying a control's Tag property on mouseover. The code works fine for standard controls such as Labels and TextBoxes but I cannot get it to work for my MenuItems (more specifically ToolStripMenuItems). Could y'all please take a look at my code and tell me what I did wrong? Thanks in advance!
public void Form1_Load(object sender, EventArgs e)
{
...
this.addEventsToAllComponents(this);
}
private void addEventsToAllComponents(Component component)
{
if (component is MenuItem)
{
MenuItem menuItem = component as MenuItem;
menuItem.Select += new EventHandler(menuItem_Select);
}
else if (component is Control)
{
Control ctrl = component as Control;
foreach (Control control in ctrl.Controls)
{
control.MouseEnter += new EventHandler(this.control_MouseEnter);
control.MouseLeave += new EventHandler(this.control_MouseLeave);
if (control.HasChildren)
addEventsToAllComponents(control);
}
}
}
private void menuItem_Select(object sender, EventArgs e)
{
MenuItem menuItem = sender as MenuItem;
if (menuItem.Tag.ToString().Length > 0)
this.toolStripStatusLabel1.Text = menuItem.Tag.ToString();
}
private void control_MouseEnter(object sender, EventArgs e)
{
Control control = sender as Control;
if (control.Tag.ToString().Length > 0)
this.toolStripStatusLabel1.Text = control.Tag.ToString();
}
private void control_MouseLeave(object sender, EventArgs e)
{
if (this.toolStripStatusLabel1.Text.ToString().Length > 0)
this.toolStripStatusLabel1.Text = "";
}
There are a few problems with your code.
1st. The Items of a MenuStrip are not children of the Item, so HasChildren will return false. Instead, they are in the Items collection of the MenuStrip. You need to handle a MenuStrip occurrence specially.
Add the following code in your AddEvents... method below:
(snip...)
// old code
if (control.HasChildren)
AddEventsToAllControls(control);
//add new code below
if (control is MenuStrip) {
MenuStrip ms = control as MenuStrip;
AddEventsToAllToolStripMenuitems(ms.Items);
}
And add the new method as follows:
private void AddEventsToAllToolStripMenuitems (ToolStripItemCollection items) {
foreach (ToolStripItem tsi in items) {
tsi.MouseEnter += new EventHandler(this.control_MouseEnter);
tsi.MouseLeave += new EventHandler(this.control_MouseLeave);
if (tsi is ToolStripMenuItem) {
ToolStripMenuItem mi = tsi as ToolStripMenuItem;
AddEventsToAllToolStripMenuitems(mi.DropDownItems);
}
}
}
2nd. ToolStripItem doesn't derive from Control, so in MouseEnter the sender as Control statement will fail (control will be null). Do something like this:
Control control = sender as Control;
if (control != null && control.Tag != null && control.Tag.ToString().Length > 0)
this.toolStripStatusLabel1.Text = control.Tag.ToString();
ToolStripItem tsi = sender as ToolStripItem;
if (tsi != null && tsi.Tag != null && tsi.Tag.ToString().Length > 0)
this.toolStripStatusLabel1.Text = tsi.Tag.ToString();
(I also added some null checks)
This should get you going.
You don't have any code to handle ToolStripMenuItems - They are not derived from MenuItems, so your MenuItem-handling code won't do anything for them.
Aside: for readability, you might like to use string.IsNullOrEmpty(menuItem.Tag.ToString()) to test for empty/blank strings.
You don't have the recursion set up for MenuItems that contain other menu items. So when it find a menuitem, it will only add the top level MenuItem, not it's children.
try adding:
foreach (MenuItem item in menuItem.MenuItems)
{
item Select += new EventHandler(menuItem_Select);
if (item.IsParent)
addEventsToAllComponents(item);
}
in the section for handling MenuItems.
Here is the revised code for AddEventsToAllComponents method:
private void addEventsToAllControls(Control ctrl)
{
foreach (Control control in ctrl.Controls)
{
control.MouseEnter += new EventHandler(this.control_MouseEnter);
control.MouseLeave += new EventHandler(this.control_MouseLeave);
if (control.HasChildren)
addEventsToAllControls(control);
if (control is MenuStrip)
{
MenuStrip ms = control as MenuStrip;
AddEventsToAllToolStripItems(ms.Items);
}
else if (control is ToolStrip)
{
ToolStrip ts = control as ToolStrip;
AddEventsToAllToolStripItems(ts.Items);
}
}
}

Categories