C# winform checkbox still checked - c#

In a button click function, I set checkbox.check = false;
but when I click button again, checkbox still in checked
here is my code:
// Header全選加上CheckBox
System.Drawing.Rectangle rect = dataGridView1.GetCellDisplayRectangle(0, -1, true);
rect.X = rect.Location.X + rect.Width / 4 - 9;
rect.Y = rect.Location.Y + (rect.Height / 2 - 9);
SolidBrush solidBrush = new SolidBrush(Color.White);
System.Windows.Forms.CheckBox checkBox = new System.Windows.Forms.CheckBox();
checkBox.Name = "checkBoxHeader";
checkBox.Size = new Size(18, 18);
checkBox.Location = rect.Location;
//checkBox.AutoCheck = false;
//MessageBox.Show(checkBox.Checked.ToString());
checkBox.Checked = false;
checkBox.Invalidate();
checkBox.Update();
dataGridView1.RefreshEdit();
checkBox.CheckedChanged += new EventHandler(checkBox_CheckedChanged);
dataGridView1.Controls.Add(checkBox);
I set MessageBox to show checkbox value, but the value is "False"
How can I set checkbox is unchecked when I click botton?
Thanks a lot

In the button click method you instantiate a new checkbox and the state of it is always set to false. You have to instantiate the checkbox and setting the properties of it in the constructor of your form or you can drag a checkbox onto the form when using the designer.
Example
private Checkbox _checkbox;
public Form1()
{
InitializeComponents();
_checkbox = new CheckBox();
//set properties
_checkbox.Checked = true;
//other properties you want to set
//add checkbox to your form for example
datagridview1.Controls.Add(_checkbox);
}
Then in your button click method just write:
_checkbox.Checked = false;

Thanks for answering, I solve this question.
I set code as
foreach (Control ckb in dataGridView1.Controls)
{
if (ckb is System.Windows.Forms.CheckBox)
{
((System.Windows.Forms.CheckBox)ckb).Checked = false;
}
}
and the checkbox is unchecked when I click button again

Related

C# How to put RadioButton inside Panel

I have searched everywhere, but the procedure are so painful. How to put multiple RadioButton into a panel programatically without using toolbox. I'm using WinForms. After several suggestion/s, I still can't add the radiobuttons inside the panel.
public partial class Form1 : Form
{
RadioButton[] RadioButton_WallFirstStorey_Yes = new RadioButton[100];
RadioButton[] RadioButton_WallFirstStorey_No = new RadioButton[100];
Panel[] Panel_WallFirstStorey = new Panel[100];
int CheckBoxWidth = 100;
public Form1()
{
InitializeComponent();
//code
//procedure
}
private void InitializeRadioButton_Wall(RadioButton RadioButtonX)
{
RadioButtonX.AutoSize = true;
RadioButtonX.Font = SystemFonts.DefaultFont;
RadioButtonX.BackColor = Color.Transparent;
Controls.Add(RadioButtonX);
}
private void InitializePanel_Wall(Panel PanelX)
{
PanelX.BackColor = Color.PaleTurquoise;
PanelX.BorderStyle = BorderStyle.Fixed3D;
PanelX.BringToFront();
Controls.Add(PanelX);
}
private void MyProcedure()
{
int i;
for (i = 1; i <= 100; i++)
{
Panel_WallFirstStorey[i] = new Panel();
InitializePanel_Wall(Panel_WallFirstStorey[i]);
Panel_WallFirstStorey[i].Location = new Point(Label_SeparatorLineVertical[ColumnMinimum + i].Location.X, Label_SeparatorLineHorizontal[RowMinimum + i].Location.Y);
Panel_WallFirstStorey[i].Width = (Label_SeparatorLineVertical[ColumnMaximum].Location.X - Label_SeparatorLineVertical[ColumnMinimum].Location.X) / (ColumnMaximum - ColumnMinimum);
Panel_WallFirstStorey[i].Height = CheckBoxWidth;
Panel_WallFirstStorey[i].SendToBack();
}
for (i = 1; i <= 100; i++)
{
RadioButton_WallFirstStorey_Yes[i] = new RadioButton();
RadioButton_WallFirstStorey_No[i] = new RadioButton();
Panel_WallFirstStorey[i].Controls.Add(RadioButton_WallFirstStorey_Yes[i]);//I add this stuff
Panel_WallFirstStorey[i].Controls.Add(RadioButton_WallFirstStorey_No[i]);//I add this stuff
InitializeRadioButton_Wall(RadioButton_WallFirstStorey_Yes[i]);
InitializeRadioButton_Wall(RadioButton_WallFirstStorey_No[i]);
RadioButton_WallFirstStorey_Yes[i].Text = "Yes";
RadioButton_WallFirstStorey_No[i].Text = "No";
RadioButton_WallFirstStorey_Yes[i].Location = new Point(Panel_WallFirstStorey[i].Width / 3, 0);
RadioButton_WallFirstStorey_No[i].Location = new Point(Panel_WallFirstStorey[i].Width * 2 / 3, 0);
RadioButton_WallFirstStorey_Yes[i].Font = SystemFonts.DefaultFont;
RadioButton_WallFirstStorey_No[i].Font = SystemFonts.DefaultFont;
RadioButton_WallFirstStorey_Yes[i].BringToFront();
RadioButton_WallFirstStorey_No[i].BringToFront();
}
}
}
Wow, your code is wrong in so many ways.... It creates controls over and over whenever a panel is painted, but it never really adds them anywere.
To add a radio button b to a panel p, it would be enough to do this:
RadioButton b = new RadioButton();
// Set properties for button here (text, location, handlers, etc.)
p.Controls.Add(b);
I'd try the following procedure instead of yours:
private void MyProcedure()
{
for (i = 1; i <= 100; i++)
{
RadioButton_WallFirstStorey_Yes[i] = new RadioButton();
RadioButton_WallFirstStorey_No[i] = new RadioButton();
InitializeRadioButton_Wall(RadioButton_WallFirstStorey_Yes[i]);
InitializeRadioButton_Wall(RadioButton_WallFirstStorey_No[i]);
RadioButton_WallFirstStorey_Yes[i].Text = "Yes";
RadioButton_WallFirstStorey_No[i].Text = "No";
RadioButton_WallFirstStorey_Yes[i].Location = new Point(Panel_WallFirstStorey[i].Location.X + Panel_WallFirstStorey[i].Width / 3, Panel_WallFirstStorey[i].Location.Y);
RadioButton_WallFirstStorey_No[i].Location = new Point(Panel_WallFirstStorey[i].Location.X + Panel_WallFirstStorey[i].Width * 2 / 3, Panel_WallFirstStorey[i].Location.Y);
Panel_WallFirstStorey[i].Controls.Add(RadioButton_WallFirstStorey_Yes[i]);
Panel_WallFirstStorey[i].Controls.Add(RadioButton_WallFirstStorey_No[i]);
}
}
The following code indicates you're still doing it wrong, adding the radio buttons to the form itself, but positioning them as if you had added them to the panel:
RadioButton_WallFirstStorey_Yes[i].Location = new Point(Panel_WallFirstStorey[i].Location.X + Panel_WallFirstStorey[i].Width / 3, Panel_WallFirstStorey[i].Location.Y);
If you added the button to the panel, it would most probably be invisible because it is outside the panel. If you added the button to the panel, you'd have to use coordinates relative to the panel's client area.
RadioButton_WallFirstStorey_Yes[i].Location = new Point(Panel_WallFirstStorey[i].Width / 3, 0);
RadioButton_WallFirstStorey_No[i].Location = new Point(Panel_WallFirstStorey[i].Width * 2 / 3, 0);
Your update code shows clearly where your error is:
private void InitializeRadioButton_Wall(RadioButton RadioButtonX)
{
RadioButtonX.AutoSize = true;
RadioButtonX.Font = SystemFonts.DefaultFont;
RadioButtonX.BackColor = Color.Transparent;
// REMOVE THIS LINE!!
Controls.Add(RadioButtonX);
}
The last line adds the radio button to the form. As we've been telling you all the time. Remove the line I marked above. Then, the radio buttons will be added to the panels only. After that it is a question of getting the positions right.
You can for example create a panel (or a GroupBox) and in a loop add the RadioButtons.
It should work like with any other control in Winforms.
// Adds 10 Radiobuttons with the name "Radio <number>"
public Form1()
{
InitializeComponent();
for (int n = 0; n < 10; n++)
{
// First instantiate a new RadioButton.
RadioButton button = new RadioButton();
// Now the name of the button.
button.Text = "Radio" + n;
// Dock the button to the top of the GroupBox (to put them in order)
button.Dock = DockStyle.Top;
// Add the button to the GroupBox.
this.groupBoxRadio.Controls.Add(button);
}
}
Your question is not very clear, and no code for context, but you should be able to create an instance of a new radiobutton and add it to the controls of the panel.
It may also be best to use RadioButtonList like Harvey has mentioned, but to try to answer your question:
var someRadioBtn = new RadioButton();
// set properties...
pnlMyPanel.Controls.Add(someRadioBtn);

Reset focus to default after Popup LostFocus

I'm observing that when the Popup control loses focus it returns focus back to the object that initiated the Popup. So basically this sequence of events.
Textbox GotFocus fires and I open the popup
When finished with the Popup user clicks anywhere outside Popup to activate LostFocus
LostFocus activates, but immediately after GotFocus for the object in step 1 (Textbox) executes - relaunching the popup.
My question, is there a way to reset focus to whatever the default is when you first start an app? I want to prevent it from returning focus back to the control that launched the popup.
EDIT: I removed LostFocus event because I found it wasn't necessary in order to remove the popup from view when user taps away.
Popup p;
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
p = new Popup();
p.IsLightDismissEnabled = true;
//p.LostFocus += p_LostFocus;
}
private void m_GotFocus(object sender, RoutedEventArgs e)
{
if (p.IsOpen != true)
{
// Create some content to show in the popup. Typically you would
// create a user control.
Border border = new Border();
border.BorderBrush = new SolidColorBrush(Colors.Black);
border.BorderThickness = new Thickness(0);
StackPanel panel1 = new StackPanel();
panel1.FlowDirection = Windows.UI.Xaml.FlowDirection.LeftToRight;
panel1.Background = new SolidColorBrush(Color.FromArgb(255, 30, 30, 30));
Button button1 = new Button();
button1.Content = ".";
button1.Margin = new Thickness(5.0);
button1.BorderThickness = new Thickness(0);
button1.Background = new SolidColorBrush(Color.FromArgb(255, 90, 90, 90));
button1.Click += new RoutedEventHandler(Feedback_Click);
TextBlock textblock1 = new TextBlock();
textblock1.Text = "";
textblock1.TextWrapping = TextWrapping.WrapWholeWords;
textblock1.Margin = new Thickness(5.0);
panel1.Children.Add(textblock1);
panel1.Children.Add(button1);
border.Child = panel1;
// Set the Child property of Popup to the border
// which contains a stackpanel, textblock and button.
p.Child = border;
// Set where the popup will show up on the screen.
p.VerticalOffset = 400;
p.HorizontalOffset = 100;
// Open the popup.
p.IsOpen = true;
}
}

Create an event handler for control created programmatically

I am working on a WPF application and what I want is if a specific Radio Button from group A is selected the program creates a second set of Radio Buttons call them group B and at the same time a disabled textbox. Now I want to create an event so if the user Selects option 3 from Group B the text box becomes enabled and when it is unselected it disables again. Now I have the working programmatically but when I try to create the event handlers I am referencing a non-existent control and it won't build. I am trying to use this.textBox.IsEnabled = true/false; to enable/disable the textbox. So just to make sure the actual question is clear. How can I enable/disable a textbox which doesn't exist at build/runtime?
My Events:
private void AllowRegion(object sender, RoutedEventArgs e)
{
this.SpecRegionText.IsEnabled = true;
}
private void DisallowRegion(object sender, RoutedEventArgs e)
{
this.SpecRegionText.IsEnabled = false;
}
Creating the controls:
private void AddSpecificControls()
{
Grid grid = (Grid)this.SpecsGrid;
RadioButton recruitmentEnabled = (RadioButton)this.RecruitmentEnabled;
if ((bool)recruitmentEnabled.IsChecked)
{
RadioButton newNations = new RadioButton();
newNations.Margin = new Thickness(10, 10, 0, 0);
newNations.HorizontalAlignment = HorizontalAlignment.Left;
newNations.Name = "NewNations";
newNations.GroupName = "RecruitType";
newNations.Content = "New Nations";
newNations.Width = 124;
grid.Children.Add(newNations);
RadioButton reFound = new RadioButton();
reFound.Margin = new Thickness(10, 30, 0, 0);
reFound.HorizontalAlignment = HorizontalAlignment.Left;
reFound.Name = "Refound";
reFound.GroupName = "RecruitType";
reFound.Content = "Refounded Nations";
reFound.Width = 124;
grid.Children.Add(reFound);
RadioButton specRegionRadio = new RadioButton();
specRegionRadio.Margin = new Thickness(10, 50, 0, 0);
specRegionRadio.HorizontalAlignment = HorizontalAlignment.Left;
specRegionRadio.VerticalAlignment = VerticalAlignment.Top;
specRegionRadio.Name = "SpecRegionRadio";
specRegionRadio.GroupName = "RecruitType";
specRegionRadio.Content = "Specific Region";
specRegionRadio.Width = 124;
specRegionRadio.Height = 23;
specRegionRadio.Checked += new RoutedEventHandler(AllowRegion);
specRegionRadio.Unchecked += new RoutedEventHandler(DisallowRegion);
grid.Children.Add(specRegionRadio);
TextBox specRegionText = new TextBox();
specRegionText.Margin = new Thickness(139, 50, 0, 0);
specRegionText.HorizontalAlignment = HorizontalAlignment.Left;
specRegionText.VerticalAlignment = VerticalAlignment.Top;
specRegionText.Name = "SpecRegionText";
specRegionText.Text = "Region";
specRegionText.Width = 120;
specRegionText.Height = 23;
specRegionText.IsEnabled = false;
grid.Children.Add(specRegionText);
}
}
You can hook delegate inline using lambda but for that you have to declare textBox before radioButton.
TextBox specRegionText = new TextBox();
RadioButton specRegionRadio = new RadioButton();
specRegionRadio.Checked += (s,e) => specRegionText.IsEnabled = true;
specRegionRadio.Unchecked += (s,e) => specRegionText.IsEnabled = false;

Winforms - how to show extra fields of an item on a form

I am trying to create a form for collecting information about an item. There are two types: default item and special item. The fields of item shows on the form by default.
public class Item
{
Id
Name
Quantity
Type //default, special
}
public class SpecialItem : Item //inherits from item
{
//extra fields here
ExpiryDate
SafeForChildren
}
How will I take the extra fields of SpecialItem to user.
I think the fields of SpecialItem should not show until the user indicates he wants to add special item by selecting the type.
I think of using a tab to show extra fields
A collapsible control - I don't if this exists
Hiding the controls and showing them when necessary
Any other idea
If the two class have a clear relation between them and this relation is well comprensible to your user, I think it's a good thing to show every field.
Put all the fields inside a groupbox and add two option buttons for the Item and SpecialItem class.
By default (at form load) the Item class will be selected and the two extra field are disabled.
If the user choose the SpecialItem class option button, enable the other two fields.
I have seen this behavior in many options dialogs when selecting an option will enable other specific options.
Try this out - it simply reflects the given type and then puts the controls onto a TableLayoutPanel adds a couple of buttons and then binds two event handlers to the click event of the buttons. It is by no means a masterpeice, but I think will get you started.
public MyForm(Type typeToDisplay)
{
InitializeComponent();
PropertyInfo[] settableProperties = typeToDisplay.GetProperties(BindingFlags.Instance | BindingFlags.Public);
TableLayoutPanel panel = new TableLayoutPanel();
panel.ColumnCount = 2;
panel.RowCount = settableProperties.Length+1;
panel.Name = "LayoutPanel";
this.Controls.Add(panel);
int rowIndex = 0;
foreach (PropertyInfo info in settableProperties)
{
Label propLabel = new Label();
propLabel.Text = info.Name;
TextBox propField = new TextBox();
panel.Controls.Add(propLabel, 0, rowIndex);
panel.Controls.Add(propField, 1, rowIndex);
rowIndex++;
}
panel.Controls.Add(new Button() { Text = "OK", Name="OK" }, 0, rowIndex);
panel.Controls.Add(new Button() { Text = "Cancel", Name="Cancel" }, 1, rowIndex);
panel.Controls["Cancel"].Click += new EventHandler(CloseForm);
panel.Controls["OK"].Click += new EventHandler(SaveChanges);
panel.Height = this.Height;
panel.Width = this.Width;
}
private void CloseForm(object sender, EventArgs e)
{
this.Close();
}
private void SaveChanges(object sender, EventArgs e)
{
MessageBox.Show("Save changes was clicked!");
this.Close();
}
Here is a full example solution to demonstrate my suggestion above. Note that it is all done in code and uses only a single column, but can work with designer-produced controls (of course) and multiple columns, too. Just be sure to set all the controls in a row (say, a label and its corresponding input control) to Visible = false to have the unused rows collapse properly.
TableLayoutPanel tlp = new TableLayoutPanel();
tlp.RowStyles.Add(new RowStyle(SizeType.Absolute, 25));
tlp.RowStyles.Add(new RowStyle(SizeType.Absolute, 25));
tlp.RowStyles.Add(new RowStyle(SizeType.Absolute, 25));
tlp.RowStyles.Add(new RowStyle(SizeType.Absolute, 25));
tlp.RowStyles.Add(new RowStyle(SizeType.AutoSize));
tlp.RowStyles.Add(new RowStyle(SizeType.AutoSize));
tlp.RowStyles.Add(new RowStyle(SizeType.Absolute, 25));
TextBox b1 = new TextBox(); b1.Dock = DockStyle.Fill;
TextBox b2 = new TextBox(); b2.Dock = DockStyle.Fill;
TextBox b3 = new TextBox(); b3.Dock = DockStyle.Fill;
CheckBox special = new CheckBox(); special.Text = "Special?";
TextBox b4 = new TextBox(); b4.Dock = DockStyle.Fill; b4.Visible = false;
TextBox b5 = new TextBox(); b5.Dock = DockStyle.Fill; b5.Visible = false;
Button button = new Button(); button.Text = "Save";
special.CheckedChanged += new EventHandler((sender, args) => { b4.Visible = b5.Visible = special.Checked; });
tlp.Controls.Add(b1, 0, 0);
tlp.Controls.Add(b2, 0, 1);
tlp.Controls.Add(b3, 0, 2);
tlp.Controls.Add(special, 0, 3);
tlp.Controls.Add(b4, 0, 4);
tlp.Controls.Add(b5, 0, 5);
tlp.Controls.Add(button, 0, 6);
Controls.Add(tlp);
tlp.Dock = DockStyle.Fill;
tlp.BringToFront();

Dynamic creation of control

for (int i = 0; i < 200; i++)
{
Control control = new Control();
control = new CheckBox();
Size size = control.Size;
Point point = new Point(20, 22);
control.Location = point;
int width = size.Width + 5;
i += width;
list.Add(control);
}
foreach(Control c in list)
{
}
how do I create a new instance of checkbox? Because this way I am getting just one checkbox each time. I want to get three checkbox in each row.
Is this winforms? A first point: you don't need the new Control() each time (you simly discard it anyway when you new CheckBox(). How exactly do you want the layout to appear? Can you describe it a bit more please?
I imagine TableLayoutPanel might be a reasonable start...
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Form form = new Form();
TableLayoutPanel layout = new TableLayoutPanel();
layout.Dock = DockStyle.Fill;
form.Controls.Add(layout);
layout.AutoScroll = true;
layout.ColumnCount = 3;
// size the columns (choice just to show options, not to be pretty)
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 200));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
layout.GrowStyle = TableLayoutPanelGrowStyle.AddRows;
for (int i = 0; i < 200; i++)
{
CheckBox chk = new CheckBox();
chk.Text = "item " + i;
layout.Controls.Add(chk);
}
Application.Run(form);
}
Otherwise, you'll need to manually set the Location (or Top and Left) of each; not simple.
Your code has problems. Let's work from sample code rather than a lesson. I'll create a Panel first, nice if you want to remove the checkboxes you created. You'd probably be interested in the user clicking a checkbox so lets add an event for that. Start a new WF project and drop a button on the form. Double click it, then paste this code:
private void button1_Click(object sender, EventArgs e) {
// Give the 3 checkboxes a decent spacing
int height = this.Font.Height * 3 / 2;
// Create the panel first, add it to the form
Panel pnl = new Panel();
pnl.Size = new Size(100, 3 * height);
pnl.Location = new Point(10, 5);
this.Controls.Add(pnl);
// Make three checkboxes now
for (int ix = 0; ix < 3; ++ix) {
CheckBox box = new CheckBox();
box.Size = new Size(100, height);
// As pointed out, avoid overlapping them
box.Location = new Point(0, ix * height);
box.Text = "Option #" + (ix + 1).ToString();
box.Tag = ix;
// We want to know when the user checked it
box.CheckedChanged += new EventHandler(box_CheckedChanged);
// The panel is the container
pnl.Controls.Add(box);
}
}
void box_CheckedChanged(object sender, EventArgs e) {
// "sender" tells you which checkbox was checked
CheckBox box = sender as CheckBox;
// I used the Tag property to store contextual info, just the index here
int index = (int)box.Tag;
// Do something more interesting here...
if (box.Checked) {
MessageBox.Show(string.Format("You checked option #{0}", index + 1));
}
}
It looks like you get your 200 instances, all placed at the same point.
Instantiate 3 new checkboxes inside your loop body, set their properties accordingly and add each of them to the list. After the code above is complete, you will have 600 checkboxes.
list.Add(Control1);
list.Add(Control2);
list.Add(Control3);
I am not sure about what you are trying to do, but I cleaned up your code a bit:
for (int i = 0; i < 200; i++)
{
Control control = new CheckBox();
control.Location = new Point(20, 22);
i += control.Size.Width + 5;
list.Add(control);
}
You should not add a new instance to the list if you want to add the control you just made.
Also:
Control control = new Control();
control = new CheckBox();
Is a bit redundant. Also to not get one control at the same spot multiple times you should alter the point. Hope this helps

Categories