I have some code that create a few components on the click of a button. Something like this.
CheckBox chk = new CheckBox();
chk.Top = 50;
chk.Left = 50;
chk.Text = "Check Box Test";
chk.Name = "chkTest"
this.Controls.Add(chk);
So how do I use this component. For example I tried this but got and error saying the component didn't exist. I just want to get their values.
if(chkTest.Checked)
{
//Do this
}
Please help.
Thanks in adv.
Either create a member variable in your class called chkTest that you can use later, or retrieve it on the fly from the Controls collection when needed, like so:
CheckBox chkTest = (CheckBox)Controls["chkTest"];
if(chkTest.Checked) {
// ...
}
If you only care about the control when it is checked or unchecked, use an event.
chk.Checked += new RoutedEventHandler(CheckBox_Checked);
chk.Unchecked += new RoutedEventHandler(CheckBox_Checked);
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
CheckBox chkBox = sender as CheckBox;
if (chkBox.IsChecked.Value)
{
// Do this...
}
}
Make sure to unsubscribe from the event handlers when you are finished with them.
You're referencing chkTest but you created chk.
You could declare the Checkbox as a member variable of your page. Then you would be able to access it more easily.
Class MyPage
{
CheckBox chkTest;
// then in page load
// chkTest = new CheckBox(); ...
}
if ((Controls.Items["chkTest"] as CheckBox).Checked)
{
// Do this
}
should work, but it's not pretty to look at. :)
You could declare it as a variable, then use it like you did:
CheckBox chkTest = Controls.Items["chkTest"] as Checkbox;
if (chkTest.Checked)
{
// Do this
}
Look on this handy page for ways to manipulate and access your Control's collection of items:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controlcollection_members.aspx
Related
I have dynamically created checkbox's. I have an option "Select All". How do I select all the dynamically created checkboxes in C#?
How to select all the dynamic checkboxes which have been created?
protected void chkbox_CheckedChanged(object sender, EventArgs e)
{
CheckBox chkBtn = new CheckBox();
chkBtn = sender as CheckBox;
selectedTypeId.Add(Convert.ToInt16(chkBtn.Name));
foreach(int id in selectedTypeId)
{
Console.WriteLine(id);
}
}
Declare a global List of CheckBoxes:
List<CheckBox> boxes;
And on your program start instantiate it.
boxes = new List<CheckBox>();
Each time you dynamically add a CheckBox, also add it to your List.
CheckBox chkBtn = new CheckBox();
boxes.Add(chkBtn);
When you want to check them all at once, use a loop to go through the list.
foreach(CheckBox box in boxes)
box.Checked = true;
You can get all of the CheckBoxes of the control like so:
var checkBoxes = this.Controls.OfType<CheckBox>();
checkBoxes.ToList()?.ForEach(x=>x.Checked = true);
But typically you would put all of the checkboxes in groupbox (from ux perspective)
groupBox.Controls.Add(checkBox);
and then get them from the groupbox:
var checkBoxes = groupBox.Controls.OfType<CheckBox>();
I have set all my TextBoxs.readOnly = true; in the form by default.
But when an Edit Button is clicked.
I want it to make all the TextBoxs.readOnly = false;
I have tried;
private void btnEdit_Click(object sender, EventArgs e)
{
foreach (var textBox in this.Controls.OfType<TextBox>())
textBox.ReadOnly = false;
}
Each TextBox has a unique name.
The easiest way to do it would be this, below. But I don't want to do it that way.
txtName.ReadOnly = false;
txtAddress.ReadOnly = false;
...
With this approach you can set just TextBoxes's ReadOnly that are placed directly in your form not those that are inside another container like GroupBox or Panel. You need a recursive method for this purpose if you have more than one container (example1, example2). But Since all your TextBoxes are inside one GroupBox then simply replace this with your GroupBox's Name like this:
foreach (var textBox in groupBox1.Controls.OfType<TextBox>())
textBox.ReadOnly = false;
I have generated checkboxes dynamically and added them to a panel on a button click with below code.
foreach (string filename in filepaths)
{
CheckBox chk = new CheckBox();
chk.Text = Path.GetFileName(filename.ToString());
Panel1.Controls.Add(chk);
Panel1.Controls.Add(new LiteralControl("<br>"));
}
Now the problem is I couldn't access the checked values on another button with below code
if (!IsPostBack) {
foreach(Control c in Panel1.Controls) {
if ((c is CheckBox) && ((CheckBox) c).Checked) {
lblerr.Text = c.ToString();
}
}
}
What I found is on button click the page getting loaded so controls in panel returns null. Can anyone explain how to get the checked values.
Thanks in advance.
When creating any kind of System.Web.UI.WebControl class problematically, it does not implicitly get re-created when the page is rebuilt during post back. You must call the method that creates the controls again in PageLoad:
protected void Page_Load(object sender, EventArgs e)
{
if(!this.IsPostback)
BuildCheckBoxes();
}
private void BuildCheckBoxes()
{
foreach (string filename in filepaths)
{
CheckBox chk = new CheckBox();
chk.Text = Path.GetFileName(filename.ToString());
Panel1.Controls.Add(chk);
Panel1.Controls.Add(new LiteralControl("<br>"));
}
}
This must be done in PageLoad, so that the controls exist when the ViewState is restored. Otherwise, .NET will discard the view state for the controls that "no longer exist".
Keep in mind that this will create overhead on your PageLoad event, if you are building a large number of controls. One way to mitigate this is to stuff controls into the server's cache, but there are a couple of very important things to note when using this method:
The property this.Page.Cache is NOT local to the page. Anything you put in here is shared across the whole of the App Pool (even the MSDN page on this property is misleading).
Each value that you put in must be referenced by a specific key that is unique for each user's session (since, as #1 points out, this cache is global across all sessions). This means the key should include something that uniquely identifies the current session, such as the session key.
private int DynCheckBoxCount
{
get { return (int)this.ViewState["DynCheckBoxCount"]; }
set { this.ViewState["DynCheckBoxCount"] = value; }
}
private void BuildCheckBoxes()
{
if (!this.IsPostBack)
{
int i = 0;
foreach (string filename in filepaths)
{
CheckBox chk = new CheckBox();
chk.Text = Path.GetFileName(filename); // Don't do a .ToString() on a string. It's unnecessary, ugly code, and opens the door for NullReferenceExceptions.
chk.Style.Add(HtmlTextWriterStyle.Display, "block");
Panel1.Controls.Add(chk);
string key = string.Format("{0}_{1}", this.Session.SessionID, i++);
this.Page.Cache[key] = chk;
}
this.DynCheckBoxCount = i;
}
else
{
for (int i = 0; i < this.DynCheckBoxCount; i++)
{
string key = string.Format("{0}_{1}", this.Session.SessionID, i);
CheckBox chk = (CheckBox)this.Page.Cache[key];
this.Panel1.Controls.Add(chk);
}
}
}
I have created a Checkbox dynamically by this button code
private void btn_add_record_Click(object sender, EventArgs e)q2
{
CheckBox DeleteCheckBox = new CheckBox();
Point P_request = new Point(nXCheckBox, nYCheckBox);
DeleteCheckBox.Location = P_request;
DeleteCheckBox.Name = "CH"+Record_ID+"";
}
Then i Checked it manually
Then i need to check a specific checkbox its name is "CH"+Record_ID+" to be checked or not dynamically using this code
string ChechBoxName = "CH1";
CheckBox DeleteChechBox = new CheckBox();
DeleteChechBox.Name = ChechBoxName;
if (DeleteChechBox.Checked)
{
// To Do Code
}
When i debug this code, it doesn't enter the if statement .. WHY ?
You're checking if the box is checked before it gets checked. Add
DeleteChechBox.CheckedChanged += DeleteChechBoxCheckedChanged;
and add the method DeleteChechBoxCheckedChanged where you can test whether or not it's been checked. You can also use
DeleteChechBox.Checked = true;
to check the box through code.
Edit:
To get a certain checkbox by it's name you have to either store it as a global variable or look through the controls array in the form.
foreach (Control control in this.Controls)
{
if (control.Name == "CH1")
{
CheckBox DeleteChechBox = (CheckBox)control;
if (DeleteChechBox.Check)
{
//To Do Code
}
}
}
When you create a new CheckBox, the default Checked value is false. Therefore if (DeleteChechBox.Checked)
returns false which is why you don't enter the block. You're not checking any existing Checkboxes, you're checking the new one you created.
In WPF you can accomplish it like shown in the following code snippet (pertinent to your example):
string _strCheckBoxName = "CH1";
CheckBox DeleteCheckBox= new CheckBox();
DeleteCheckBox.Name = _strCheckBoxName ;
DeleteCheckBox.Checked+=(s,e)=>CheckBox_Change(s,e);
DeleteCheckBox.Unchecked+=(s,e)=>CheckBox_Change(s,e);
DeleteCheckBox.IsChecked = true;
private void CheckBox_Change(object sender, RoutedEventArgs e)
{
if ((sender as CheckBox).Name=_strCheckBoxName && (bool)(sender as CheckBox).IsChecked)
{
// To Do Code
}
}
In suggested solution, you essentially subscribe the newly created CheckBox control to a single event handler proc, which looks at the control name and if checked runs some code. If more CheckBox added, then use the same event-subscription technique pointed to the same handler, and extend it with another if statement (or if-else if, or switch statement).
Hope this will help. Rgds,
Your problem is that you are creating one CheckBox in your btn_add_record_Click handler and then creating a new one in your second code fragment, which just happens to have the same Name as the first. That notwithstanding, it is not the same check box, so will not have the same value for its Checked property.
The way to fix that is to create the checkbox in the form's constructor as a class member, and then discover it when you need it by searching the components, using the code which Xylorast showed:
foreach (Control control in this.Controls)
{
if (control.Name == "CH1")
{
CheckBox DeleteChechBox = (CheckBox)control;
if (DeleteChechBox.Check)
{
//To Do Code
}
}
}
This is what I meant. Maybe you already checked it..?
string ChechBoxName = "CH1";
CheckBox DeleteChechBox = new CheckBox();
DeleteChechBox.Name = ChechBoxName;
DeleteChechBox.Checked = true;
if (DeleteChechBox.Checked)
{
// To Do Code
}
Edit:
Here is another way of accessing the control instead of enumerating over all the controls on the form for each control you would like to access:
Dictionary<string, CheckBox> checkBoxCollection = new Dictionary<string, CheckBox>();
And in your method where you create the checkbox add it to the dictionary:
checkBoxCollection.Add("CH1",DeleteCheckBox);
Access the checkbox from wherever you want like this:
CheckBox checkBox;
bool success = controls.TryGetValue("CH1"), out checkBox);
if (success)
{
// To Do Code
}
Or in your CheckedEvent you can get the CheckBox being checked like this:
CheckBox checkBox = sender as CheckBox;
I'm creating a ToolStripMenu shown below that is supposed to allow the user to interact with the items "XML" and "Non XML" as though they are regular check boxes on a form. However, when one item is checked/unchecked the menu closes. How can I allow an item to be checked/unchecked without closing the menu? Or is there a different standard method of achieving the same behavior?
So what I want is to be able to click on "Non XML", show a check box and leave the menu open.
The idea is that the last menu item will be "Done" and when it's clicked the "G2S" sub items will remain open but the "Display" sub items ( XML, Non XML ) will close.
Any ideas?
Note: I am aware that this is likely not the best user interface design. I'd like to know however how this could be accomplished just to gain some technical knowledge about handling menus.
Interesting concept is described in this thread on Stackoverflow:
Here is the essence of the accepted answer:
ParentMenu.DropDown.AutoClose = false;
It does exactly what you are asking for - prevent menu from closing when subitem is clicked.
Here's a useful extension that requires user to click outside of menu item + dropdowns to close.
public static void KeepOpenOnDropdownCheck (this ToolStripMenuItem ctl)
{
foreach (var item in ctl.DropDownItems.OfType<ToolStripMenuItem>())
{
item.MouseEnter += (o, e) => ctl.DropDown.AutoClose = false;
item.MouseLeave += (o, e) => ctl.DropDown.AutoClose = true;
}
}
Posted in case somebody finds it helpful.
Instead of trying to do exactly what I had originally intended, I've come up with the following:
1- Use a ContextMenuStrip
2- When the user clicks on the ToolStripMenu item I display the ContextMenuStrip at a location near the menu item as shown below: ( note the positioning still needs adjusting )
To get this working I build the ContextMenuStrip in code at run-time so that the items in the ContextMenuStrip can be build dynamically based on the situation.
Code snippets:
Show the ContextMenuStrip when the menu item is clicked:
private void filterToolStripMenuItem_Click(object sender, EventArgs e)
{
contextMenuStrip1.Show(this, 180, 20);
}
Build the ContextMenuStrip:
if (protInfo.Name == "QCOM" )
{
BroadCast = new CheckBox();
BroadCast.Text = "Date/Time Broadcast";
BroadCast.Checked = FlagSet(CurrentFilter, (Byte)Filter.DateTimeBC);
ToolStripControlHost Ch1 = new ToolStripControlHost(BroadCast);
GenPoll = new CheckBox();
GenPoll.Text = "Status Poll";
GenPoll.Checked = FlagSet(CurrentFilter, (Byte)Filter.GenStatusPoll);
ToolStripControlHost Ch2 = new ToolStripControlHost(GenPoll);
GenPollResp = new CheckBox();
GenPollResp.Text = "Status Poll Response";
GenPollResp.Checked = FlagSet(CurrentFilter, (Byte)Filter.GenStatusResponse);
ToolStripControlHost Ch3 = new ToolStripControlHost(GenPollResp);
Button btnDone = new Button();
btnDone.Text = "Done";
ToolStripControlHost Ch4 = new ToolStripControlHost(btnDone);
btnDone.Click += new EventHandler(btnDone_Click);
contextMenuStrip1.Items.Clear();
contextMenuStrip1.Items.Add(Ch1);
contextMenuStrip1.Items.Add(Ch2);
contextMenuStrip1.Items.Add(Ch3);
contextMenuStrip1.Items.Add(Ch4);
contextMenuStrip1.Enabled = true;
filterToolStripMenuItem.Enabled = true;
}
else
{
filterToolStripMenuItem.Enabled = false;
}
This may not be the best user interface design, but it seems to work.
The original solution will work with the use of mouse events.
On mouse enter event:
parent.dropdown.autoclose = false;
on mouse leave event:
parent.dropdown.autoclose = true;
The only catch is if the user access the menu items by other means than a mouse.
I used a combination of Neolisk's and Chimera's answers to allow deletion of multiple leaf items from a treeview. My solution is below
Note: the following Items created at design time are used:
TreePromotions (TreeView)
menuVendorSection (Context Menu Strip)
removeMultipleItemsToolStripMenuItem (DropDown of menuVendorSection)
private void removeMultipleItemsToolStripMenuItem_MouseHover(object sender, EventArgs e)
{
removeMultipleItemsToolStripMenuItem.DropDownItems.Clear();
ToolStripMenuItem detailMenuItem;
TreeNode vendorSectionNode = treePromotions.SelectedNode;
for (int vsn = 0; vsn < vendorSectionNode.Nodes.Count; vsn++)
{
//add checkbox item
detailMenuItem = new ToolStripMenuItem(vendorSectionNode.Nodes[vsn].Text);
detailMenuItem.Tag = vendorSectionNode.Nodes[vsn].Tag;
detailMenuItem.CheckOnClick = true;
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(detailMenuItem);
}
//add action buttons
Button buttonDeleteMultiple = new Button();
buttonDeleteMultiple.Text = "Remove Checked Items";
ToolStripControlHost buttonHost = new ToolStripControlHost(buttonDeleteMultiple);
buttonDeleteMultiple.Click += new EventHandler(buttonDeleteMultiple_Click);
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(buttonHost);
Button buttonCancelMultipleDelete = new Button();
buttonCancelMultipleDelete.Text = "CANCEL";
buttonHost = new ToolStripControlHost(buttonCancelMultipleDelete);
buttonCancelMultipleDelete.Click += new EventHandler(buttonCancelMultipleDelete_Click);
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(buttonHost);
removeMultipleItemsToolStripMenuItem.DropDown.AutoClose = false;
menuVendorSection.AutoClose = false;
}
private void buttonDeleteMultiple_Click(object sender, EventArgs e)
{
//delete items
for (int dmi = 0; dmi < removeAllItemsToolStripMenuItem.DropDownItems.Count - 2; dmi++) //do not include buttons
{
((Detail)removeAllItemsToolStripMenuItem.DropDownItems[dmi].Tag).Delete(); //deletes item from database
}
//rebuild leaf
treePromotions.SelectedNode.Nodes.Clear();
addItemNodes(treePromotions.SelectedNode); //builds leaf nodes from database
//close menus
removeMultipleItemsToolStripMenuItem.DropDown.Close();
menuVendorSection.AutoClose = true;
menuVendorSection.Close();
}
private void buttonCancelMultipleDelete_Click(object sender, EventArgs e)
{
//just close menus
removeMultipleItemsToolStripMenuItem.DropDown.Close();
menuVendorSection.AutoClose = true;
menuVendorSection.Close();
}
If someone is still interested, here is a vb solution:
1) For the parent tool strip menu item, add the following handler in the form's constructor:
AddHandler ParentTSMI.DropDown.Closing, AddressOf onDropDownClosing
2) The handler:
Private Sub onDropDownClosing(sender As Object, e As ToolStripDropDownClosingEventArgs)
If e.CloseReason = ToolStripDropDownCloseReason.ItemClicked Then
e.Cancel = True
End If
End Sub
That's it all.
Don't forget to remove the handler (RemoveHandler) when you close the form.