Trouble of Handle Control Event in Class C# - c#

I have made a class that contain such as form,button, etc in class. then i create the handle events of them in class. Take a look at my class code below:
public static class InputBox
{
static Form form = new Form();
static Label label = new Label();
static TextBox textBox = new TextBox();
static Button buttonOk = new Button();
static Button buttonCancel = new Button();
public static DialogResult Show(string title, string promptText, ref string value)
{
form.Text = title;
label.Text = promptText;
textBox.Text = value;
buttonOk.Text = "OK";
buttonCancel.Text = "Cancel";
buttonOk.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;
label.SetBounds(9, 20, 372, 13);
textBox.SetBounds(12, 36, 372, 20);
buttonOk.SetBounds(228, 72, 75, 23);
buttonCancel.SetBounds(309, 72, 75, 23);
label.AutoSize = true;
textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
form.ClientSize = new Size(396, 107);
form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
buttonOk.Click += new EventHandler(buttonOk_Click); //this is the handle code
buttonCancel.Click += new EventHandler(buttonCancel_Click);//this is the handle code
form.MinimizeBox = false;
form.MaximizeBox = false;
form.AcceptButton = buttonOk;
form.CancelButton = buttonCancel;
DialogResult dialogResult = form.ShowDialog();
value = textBox.Text;
return dialogResult;
}
static void buttonCancel_Click(object sender, EventArgs e)
{
form.Close();
}
static void buttonOk_Click(object sender, EventArgs e)
{
MessageBox.Show("If u click this, You Will Get many Messages as many as you call the class");
}
}
then, i call it like this in my own form code:
string strbuffer; // Global Variable
InputBox.Show("Hi..?", "What Is Your Name?",ref strbuffer);
//do something...
InputBox.Show("Hi..?", "What Is Your Age?",ref strbuffer);
//do something
InputBox.Show("Hi..?", "How Many Cars do you have?",ref strbuffer);
//do something
if i call the Class as many as i call it, the old handler will never get dispose so the code in handler control will be excuted as many as you call the class
i guess the variable doesn't get dispose when the class is unused anymore so the variable always accumulate every times you call it
What would be the best way to solve this case?

I am not sure what you are asking but if its event related problem I would suggest deallocating the event.
static void buttonCancel_Click(object sender, EventArgs e)
{
form.Close();
buttonOk.Click -= new EventHandler(buttonOk_Click);
buttonCancel.Click -= new EventHandler(buttonCancel_Click);
}
static void buttonOk_Click(object sender, EventArgs e)
{
MessageBox.Show("If u click this, You Will Get many Messages as many as you call the class");
buttonOk.Click -= new EventHandler(buttonOk_Click);
buttonCancel.Click -= new EventHandler(buttonCancel_Click);
}

Here, I've moved the static variables for form, label, textbox etc into the Show method.
This means you get a new instance of these each time you call this method. Hence the Event is not already attached to it.
The event handler then had to change to not reference the static form (that doesn't exist anymore) so we got the reference to the form instance from the button.
public static class InputBox
{
public static DialogResult Show(string title, string promptText, ref string value)
{
Form form = new Form();
Label label = new Label();
TextBox textBox = new TextBox();
Button buttonOk = new Button();
Button buttonCancel = new Button();
form.Text = title;
label.Text = promptText;
textBox.Text = value;
buttonOk.Text = "OK";
buttonCancel.Text = "Cancel";
buttonOk.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;
label.SetBounds(9, 20, 372, 13);
textBox.SetBounds(12, 36, 372, 20);
buttonOk.SetBounds(228, 72, 75, 23);
buttonCancel.SetBounds(309, 72, 75, 23);
label.AutoSize = true;
textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
form.ClientSize = new Size(396, 107);
form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
buttonOk.Click += new EventHandler(buttonOk_Click); //this is the handle code
buttonCancel.Click += new EventHandler(buttonCancel_Click);//this is the handle code
form.MinimizeBox = false;
form.MaximizeBox = false;
form.AcceptButton = buttonOk;
form.CancelButton = buttonCancel;
DialogResult dialogResult = form.ShowDialog();
value = textBox.Text;
return dialogResult;
}
static void buttonCancel_Click(object sender, EventArgs e)
{
(sender as Button).FindForm().Close();
}
static void buttonOk_Click(object sender, EventArgs e)
{
MessageBox.Show("If u click this, You Will Get many Messages as many as you call the class");
}
}

Related

How can I use a textbox, label and button that was added to a panel to input and show information

Okay so basically I have a calendar display and when you click on anyone of the dates on it, it creates a new panel with a label displaying the date selected. I also made it so when you click on a date and a new panel is made, a label, textbox and button is created and placed onto that new panel as well.
So what I want and have been struggling with is for me to enter something into that textbox then to press the button to submit it and then for it to show on the label.
I think I know what the issue is but I've been stuck at this for hours.
Here is my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void monthCalendar1_DateSelected_1(object sender, DateRangeEventArgs e)
{
Panel newPanel = new Panel();
this.Controls.Add(newPanel);
newPanel.Visible = true;
newPanel.Size = new Size(564, 831);
newPanel.Location = new Point(0, 190);
newPanel.BringToFront();
Label textLabel = new Label();
textLabel.Size = new Size(500, 500);
textLabel.Font = new Font(textLabel.Font.Name, 25, textLabel.Font.Style);
textLabel.Location = new Point(3, 3);
Label dateLabel = new Label();
dateLabel.Size = new Size(500, 500);
dateLabel.Font = new Font(dateLabel.Font.Name, 25, dateLabel.Font.Style);
dateLabel.Location = new Point(128, 3);
Button Submitbutton = new Button();
Submitbutton.Location = new Point(100, 500);
Submitbutton.Text = "Add Food";
Submitbutton.Size = new Size(400, 100);
Submitbutton.BackColor = Color.Aqua;
Submitbutton.BringToFront();
Submitbutton.Click += Button_Click;
TextBox textBox = new TextBox();
textBox.Location = new Point(100, 650);
textBox.Size = new Size(500, 500);
textBox.BackColor = Color.Aqua;
textBox.Visible = true;
textBox.Text = "Enter food here...";
textBox.BringToFront();
Label inputtedFood = new Label();
inputtedFood.Size = new Size(500, 500);
inputtedFood.Font = new Font(inputtedFood.Font.Name, 25, inputtedFood.Font.Style);
inputtedFood.Location = new Point(100, 600);
inputtedFood.Text = "placeholder";
newPanel.Controls.Add(dateLabel);
newPanel.Controls.Add(textLabel);
newPanel.Controls.Add(Submitbutton);
newPanel.Controls.Add(textBox);
newPanel.Controls.Add(inputtedFood);
String myCalendar = monthCalendar1.SelectionRange.Start.ToShortDateString();
textLabel.Text = "Date:";
dateLabel.Text = myCalendar;
}
private void Button_Click(object sender, EventArgs e)
{
inputtedFood.Text = textBox.Text;
}
private void monthCalendar1_DateChanged_1(object sender, DateRangeEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
}
}
I tried the above code and was met with errors that are shown in the post.
Totally agree with both LarsTech and Ňɏssa Pøngjǣrdenlarp, you should be building a UserControl in place of the Panel and placing the TextBox, Button, and Label inside of that.
Your immediate question, though:
So what I want and have been struggling with is for me to enter
something into that textbox then to press the button to submit it and
then for it to show on the label.
Can be accomplished with this simple code:
Button Submitbutton = new Button();
// ... more code ...
Submitbutton.Click += (s2, e2) =>
{
inputtedFood.Text = textBox.Text;
};
Here's a little example showing it in action:
private void button1_Click(object sender, EventArgs e)
{
FlowLayoutPanel flp = new FlowLayoutPanel();
TextBox textBox = new TextBox();
// ... more code ...
Label inputtedFood = new Label();
inputtedFood.Text = "placeholder";
// ... more code ...
Button Submitbutton = new Button();
// ... more code ...
Submitbutton.Click += (s2, e2) =>
{
inputtedFood.Text = textBox.Text;
};
flp.Controls.Add(textBox);
flp.Controls.Add(Submitbutton);
flp.Controls.Add(inputtedFood);
flowLayoutPanel1.Controls.Add(flp);
}
The output:

Can't debug automated tests after adding a new Winform

I have some auto tests hitting web UI pages and web services using Selenium and NUnit. I recently added a dynamically created Windows form, which is displayed as a modal dialog and expects some user input like passwords, etc. Once the input has been entered, the settings are saved and encrypted using DPAPI and on a subsequent run, do not need user input anymore.
My issue is that I can debug up to the point where the dialog is displayed but as soon as the code reaches the modal dialog, Visual Studio just hangs. I can run the code and it works perfectly fine. I just can't debug it. Has anyone seen this issue before?
Code for user prompt:
public static class TestSettingsConfigExtensions
{
....
private static string PromptUserForSetting(string settingName)
{
string promptedValue = null;
DialogResult result = UserInput.Show("User Setting", $"Please enter a value for {settingName}", ref promptedValue);
if (result == DialogResult.OK)
return promptedValue;
return null;
}
private class UserInput
{
public static DialogResult Show(string title, string promptText, ref string value)
{
Form form = new Form();
Label lblPrompt = new Label();
TextBox txtSettingValue = new TextBox();
txtSettingValue.UseSystemPasswordChar = true;
Label lblUnmask = new Label();
CheckBox chkShouldUnmask = new CheckBox();
chkShouldUnmask.CheckedChanged += (object sender, EventArgs e) => { ChkShouldUnmask_CheckedChanged(chkShouldUnmask.Checked, ref txtSettingValue); };
Button btnOk = new Button();
Button btnCancel = new Button();
form.Text = title;
lblPrompt.Text = promptText;
txtSettingValue.Text = value;
lblUnmask.Text = "Unmask";
chkShouldUnmask.Checked = false;
btnOk.Text = "OK";
btnCancel.Text = "Cancel";
btnOk.DialogResult = DialogResult.OK;
btnCancel.DialogResult = DialogResult.Cancel;
lblPrompt.SetBounds(9, 20, 372, 13);
txtSettingValue.SetBounds(12, 36, 372, 20);
lblUnmask.SetBounds(9, 65, 50, 13);
chkShouldUnmask.SetBounds(59, 65, 372, 13);
btnOk.SetBounds(228, 102, 75, 23);
btnCancel.SetBounds(309, 102, 75, 23);
lblPrompt.AutoSize = true;
txtSettingValue.Anchor = txtSettingValue.Anchor | AnchorStyles.Right;
lblUnmask.AutoSize = true;
chkShouldUnmask.Anchor = chkShouldUnmask.Anchor | AnchorStyles.Right;
btnOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
btnCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
form.ClientSize = new Size(396, 137);
form.Controls.AddRange(new Control[] { lblPrompt, txtSettingValue, lblUnmask, chkShouldUnmask, btnOk, btnCancel });
form.ClientSize = new Size(Math.Max(300, lblPrompt.Right + 10), form.ClientSize.Height);
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MinimizeBox = false;
form.MaximizeBox = false;
form.AcceptButton = btnOk;
form.CancelButton = btnCancel;
DialogResult dialogResult = form.ShowDialog();
value = txtSettingValue.Text;
return dialogResult;
}
private static void ChkShouldUnmask_CheckedChanged(bool shouldUnmask, ref TextBox txtSettingValue)
{
if (shouldUnmask)
txtSettingValue.UseSystemPasswordChar = false;
else
txtSettingValue.UseSystemPasswordChar = true;
}
}
}

Create Button at runtime and save it permanently in c#

I have this code to create a button:
private void CreateButton(){
Button createButton = new Button();
// Set Button properties
createButton.Height = 40;
createButton.Width = 300;
createButton.BackColor = Color.Red;
createButton.ForeColor = Color.Blue;
createButton.Location = new Point(20, 150);
createButton.Text = "I am Button";
createButton.Name = "Button";
createButton.Font = new Font("Georgia", 16);
createButton.Click += new EventHandler(create_Button_Click);
this.Controls.Add(createButton);
}
private void create_Button_Click(object sender, EventArgs e)
{
MessageBox.Show("button is clicked");
}
and i want to save it permanently in the project. what is the best way to do this?

TextBox not activating Form accept button

I have a Form which has a TextBox and a Button. I have set the Form's AcceptButton property to my Button, and set the TextBox's AcceptsReturn property to false:
class Window : Form
{
private TextBox textBox1;
private Button btn;
public Window()
{
this.Size = new Size(200, 200);
this.AcceptButton = this.btn;
textBox1 = new TextBox();
textBox1.Location = new Point(10, 10);
textBox1.Width = 50;
textBox1.AcceptsReturn = false;
this.Controls.Add(textBox1);
btn = new Button();
btn.Text = "Test";
btn.Location = new Point(textBox1.Right + 10, 10);
btn.Click += btn_Click;
this.Controls.Add(btn);
}
void btn_Click(object sender, EventArgs e)
{
MessageBox.Show("Works");
}
}
class Program
{
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.Run(new Window());
}
}
However, when pressing the Enter key while the TextBox has focus, the AcceptButton of the Form is not activated. I worked around it using the KeyDown event of the TextBox like so:
textBox1.KeyDown += (s,e) => { if (e.KeyCode == Keys.Enter) btn.PerformClick(); } ;
And although it works I am curious as to why the earlier method using the AcceptButton property failed.
The problem is that you set the Form's AcceptButton to btn before you instantiate it. Move this.AcceptButton = this.btn; to any line AFTER btn = new Button();.. btn is pointing to a null reference up until new Button(). Once you instantiate btn you can use it to set AcceptButton.
You just wrote one line in the wrong place.That's the answer:
public Form1()
{
InitializeComponent();
this.Size = new Size(200, 200);
textBox1 = new TextBox();
textBox1.Location = new Point(10, 10);
textBox1.Width = 50;
textBox1.AcceptsReturn = true;
this.Controls.Add(textBox1);
btn = new Button();
btn.Text = "Test";
btn.Location = new Point(textBox1.Right + 10, 10);
btn.Click += btn_Click;
this.Controls.Add(btn);
this.AcceptButton = this.btn;
}
I hope this helps you!

Show WinFrm from C# console application and wait to close

I am trying to show a WinForm (inputbox) from a console application in C# and wait until the user closes the form. It is important for me to have the inputbox ontop and active when it opens. ShowDialog() is not working in my case as in some cases it does not appears as an active form. So I'd like to change my code and use Show(). This way I can manually make find out if the form is active or not and if not activate it myself. With ShowDialog(). my code stops and I can not do anything until the from is closed.
Below is my code. It does show the inputbox, however it is frozen. What am I doing wrong please? As clear the while-loop after "inputBox.Show();" is not doing anything, but if I can manage to run the loop and the inputbox does not freeze, I will sort out the rest myself. I appreciate your help.
public static string mInputBox(string strPrompt, string strTitle, string strDefaultResponse)
{
string strResponse = null;
Form inputBox = new Form();
inputBox.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
inputBox.ClientSize = new Size(500, 85);
inputBox.Text = strTitle;
inputBox.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
inputBox.Left = (Screen.PrimaryScreen.Bounds.Size.Width / 2) - (inputBox.ClientSize.Width / 2);
inputBox.Top = (Screen.PrimaryScreen.Bounds.Size.Height / 2) - (inputBox.ClientSize.Height / 2);
Label lblPrompt = new Label();
lblPrompt.Text = strPrompt;
inputBox.Controls.Add(lblPrompt);
TextBox textBox = new TextBox();
textBox.Text = strDefaultResponse;
inputBox.Controls.Add(textBox);
Button okButton = new Button();
okButton.Text = "&OK";
inputBox.Controls.Add(okButton);
Button cancelButton = new Button();
cancelButton.Text = "&Cancel";
inputBox.Controls.Add(cancelButton);
okButton.Click += (sender, e) =>
{
strResponse = textBox.Text;
inputBox.Close();
};
cancelButton.Click += (sender, e) =>
{
inputBox.Close();
};
inputBox.AcceptButton = okButton;
inputBox.CancelButton = cancelButton;
SetWindowPos(inputBox.Handle, HWND_TOPMOST, inputBox.Left, inputBox.Top, inputBox.Width, inputBox.Height, NOACTIVATE);
inputBox.Show();
while {true}
Thread.Sleep(100);
Application.DoEvents();
return strResponse;
}
I'm not sure why you are taking this route, I'm sure there are better ways to do it (explain one at the end). however to make your code run you should add Application.DoEvents() inside your loop
the code should be something like this:
var formActive = true;
inputBox.FormClosed += (s, e) => formActive = false;
inputBox.Show();
inputBox.TopMost = true;
inputBox.Activate();
while (formActive)
{
Thread.Sleep(10);
Application.DoEvents();
}
and the whole method will be:
public static string mInputBox(string strPrompt, string strTitle, string strDefaultResponse)
{
string strResponse = null;
Form inputBox = new Form();
inputBox.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
inputBox.ClientSize = new Size(500, 85);
inputBox.Text = strTitle;
inputBox.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
inputBox.Left = (Screen.PrimaryScreen.Bounds.Size.Width/2) - (inputBox.ClientSize.Width/2);
inputBox.Top = (Screen.PrimaryScreen.Bounds.Size.Height/2) - (inputBox.ClientSize.Height/2);
Label lblPrompt = new Label();
lblPrompt.Text = strPrompt;
inputBox.Controls.Add(lblPrompt);
TextBox textBox = new TextBox();
textBox.Text = strDefaultResponse;
inputBox.Controls.Add(textBox);
Button okButton = new Button();
okButton.Text = "&OK";
inputBox.Controls.Add(okButton);
Button cancelButton = new Button();
cancelButton.Text = "&Cancel";
inputBox.Controls.Add(cancelButton);
okButton.Click += (sender, e) =>
{
strResponse = textBox.Text;
inputBox.Close();
};
cancelButton.Click += (sender, e) =>
{
inputBox.Close();
};
inputBox.AcceptButton = okButton;
inputBox.CancelButton = cancelButton;
var formActive = true;
inputBox.FormClosed += (s, e) => formActive = false;
inputBox.Show();
inputBox.TopMost = true;
inputBox.Activate();
while (formActive)
{
Thread.Sleep(10);
Application.DoEvents();
}
return strResponse;
}
but I think it would be a better Idea to Derive from Form and create a InputBox and set TopMost and call Activate OnLoad to create what you need, then simply call ShowDialog, something like:
class Inputbox : Form
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
TopMost = true;
Activate();
}
}
and better to put UI code in InputBox class as the whole code and usage would be like:
class Inputbox : Form
{
public string Response { get; set; }
public Inputbox(string strTitle, string strPrompt, string strDefaultResponse)
{
//add UI and Controls here
FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
ClientSize = new Size(500, 85);
Text = strTitle;
StartPosition = System.Windows.Forms.FormStartPosition.Manual;
Left = (Screen.PrimaryScreen.Bounds.Size.Width/2) - (ClientSize.Width/2);
Top = (Screen.PrimaryScreen.Bounds.Size.Height/2) - (ClientSize.Height/2);
Label lblPrompt = new Label();
lblPrompt.Text = strPrompt;
Controls.Add(lblPrompt);
TextBox textBox = new TextBox();
textBox.Text = strDefaultResponse;
Controls.Add(textBox);
Button okButton = new Button();
okButton.Text = "&OK";
Controls.Add(okButton);
Button cancelButton = new Button();
cancelButton.Text = "&Cancel";
Controls.Add(cancelButton);
okButton.Click += (sender, e) =>
{
Response = textBox.Text;
Close();
};
cancelButton.Click += (sender, e) =>
{
Close();
};
AcceptButton = okButton;
CancelButton = cancelButton;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
TopMost = true;
Activate();
}
}
public static string mInputBox(string strPrompt, string strTitle, string strDefaultResponse)
{
string strResponse = null;
Inputbox inputBox = new Inputbox(strPrompt,strTitle,strDefaultResponse);
inputBox.ShowDialog();
return inputBox.Response;
}
You need to run a message loop:
Application.Run(inputBox);

Categories

Resources