i currently have one form and a few user control, i have a panel set from the Form1 - mainpanel, so that whenever i click a button, one of the user control will be showing on the mainPanel.
my problem is that one of the control(InfoSetting) has some other new buttons, and when i click it I would like the mainPanel to show the new user control. However, right now all other buttons from Form1 is working fine, but when I click on the InfoSetting button, nothing seems to show up.
here is my code from Form1
public partial class Form1 : MetroFramework.Forms.MetroForm
{
InfoSettings infoSetting;
CashSales cashSales;
PriceSetting priceSetting;
public Form1()
{
InitializeComponent();
infoSetting = new InfoSettings();
cashSales = new CashSales();
priceSetting = new PriceSetting();
}
protected void ButtonClicked(object sender, EventArgs e)
{
buttonHandler(sender);
}
public void buttonHandler(object sender)
{
Button button = sender as Button;
mainPanel.Controls.Clear();
if (button != null)
{
switch (button.Name)
{
case "HomeBtn":
infoSetting.Dock = DockStyle.Fill;
mainPanel.Controls.Add(infoSetting);
break;
case "cashSalesBtn":
cashSales.Dock = DockStyle.Fill;
mainPanel.Controls.Add(cashSales);
break;
case "settingBtn":
infoSetting.Dock = DockStyle.Fill;
mainPanel.Controls.Add(infoSetting);
break;
case "priceSettingBtn":
cashSales.Dock = DockStyle.Fill;
mainPanel.Controls.Add(cashSales);
break;
default:
mainPanel.Controls.Clear();
break;
}
}
}
and here is the code from the InfoSetting user control
public partial class InfoSettings : UserControl
{
public InfoSettings()
{
InitializeComponent();
}
private void priceSettingBtn_Click(object sender, EventArgs e)
{
Form1 form1 = new Form1();
form1.buttonHandler(sender);
}
}
as stuartd said you can add a call to your parent Form:
public partial class InfoSettings : UserControl
{
public InfoSettings()
{
InitializeComponent();
}
private void settingBtn_Click(object sender, EventArgs e)
{
Form1 form1 = (Form1) this.Parent;
form1.buttonHandler(sender);
}
}
It would probably be better to have a common class that you can access in both form and user control and have the code you want to run in a method there. Something like:
public class FormHelper
{
public void CodeIWantToRunIn2Places()
{
// Implementation Here
}
}
You can implement the above as a singleton so you have access in both places. Then in your form classes you could do:
FormHelper.Instance.CodeIWantToRunIn2Places();
In your event handler as well as in your user control.
You can make the Form 1 as "static" and also the method buttonHandler(object sender) as "static" as well.
Then inside the priceSettingBtn_Click, call the below function directly
Form1.buttonHandler(sender);
I would have a global object with a pointer to all the forms in the application.
public Global
{
public Form1 MainForm;
public Dialog1 D1;
...
}
public static Global = new Global();
In as each form is created
Global.MainForm = form1;
then you can go
private void priceSettingBtn_Click(object sender, EventArgs e)
{
Global.MainForm.buttonHandler(sender);
}
As other have said , its probably better to not call the click handler, its better to have this code and the real click handler call a business logic level function
Related
This is a demo example, I can't use the original code. This context is very simplified.
I want to call a button/event from the child form (form2) when I'm clicking a button from the mother form (form1). I want to do this via subscribing (which I don't really understard since I'm new to coding).
Mother form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.Show();
//Call the Button from Form2 here
}
}
Child Form:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("MessageBox called from Form1 or Form2");
}
}
What you want to do, the way you want to do it, is in general not a good idea as you should not be relying on UI controls on another from, from your other form.
What you can do to achieve what you asked for without rewriting anything is more like this:
1) in the button click of Form2, you do not do anything else than calling a method on Form2, event handler contains no other logic
2) you make that method of form2 public
3) from your button click on form1, you call that same public method of form2
again, this would work but it is not necessarily the best design, it really depends on the whole architecture of your app if this fits or not with the rest or there are better and different ways to accomplish this.
Don't call other form "button clicks", if you want to call some logic from different places, extract logic into dedicated class and call it from both places
public class MyLogic
{
public void Execute(string someParameter)
{
// Do something with parameter
}
}
Then use it in both forms
public partial class Form1 : Form
{
private readonly MyLogic _importantLogic;
public Form1()
{
InitializeComponent();
_importantLogic = new MyLogic();
}
private void button1_Click(object sender, EventArgs e)
{
_importantLogic.Execute(this.textBox1.Text);
}
}
public partial class Form2 : Form
{
private readonly MyLogic _importantLogic;
public Form2()
{
InitializeComponent();
_importantLogic = new MyLogic();
}
private void button1_Click(object sender, EventArgs e)
{
_importantLogic.Execute("Always Form 2");
}
}
I am new to c# and using windows forms.
I have Form1 with a button (Button_Save) and textbox . and I have user control1 with one button (button1).
What I am trying to do in this program is: when I click on button1, its text appear in textbox (in Form1), then I enter new text and click save, the button1 text change accordingly.
I will explain when the freeze happens:
There are 2 parts:
first part: when I created instance of user control1 in Form1 then I participated in UserControl1Event and run program it works fine and button1 text appears in textbox when I click on it. Second part when I create instance of Form1 in user control1 and participated in Form1Event and run the program the program freezes for long time then gives error pointing at Form1 instance in user control1 (as shown in screen shot).
Anyone knows why this is happening ? what I am doing wrong?
Form1:
public partial class Form1 : Form
{
public event EventHandler Form1Event;
UserControl1 uc1 = new UserControl1();
public Form1()
{
InitializeComponent();
Controls.Add(uc1);
uc1.Visible = true;
uc1.UserControl1Event += new EventHandler(Handleuc1);
}
string Return_TextBox_Txt;
public string TextBox_Txt
{
get { return Return_TextBox_Txt; }
}
public void Handleuc1(object sender, EventArgs e) ////////////Handle uc1 event
{
textBox1.Text = uc1.ButtonText;
}
private void button_save__Click(object sender, EventArgs e)//change button text
{
Return_TextBox_Txt = textBox1.Text;
Form1Event(this, e);
}
}
User Control1:
public partial class UserControl1 : UserControl
{
string BtnTxt;
Form1 frm1 = new Form1();
public event EventHandler UserControl1Event;
public string ButtonText
{
get { return BtnTxt; }
}
private void UserControl1_Load(object sender, EventArgs e)
{
frm1.Form1Event += new EventHandler(HandleForm1Event);
}
public void HandleForm1Event(object sender, EventArgs e)
{
button1.Text = frm1.TextBox_Txt;
}
private void Button1_Click(object sender, EventArgs e)
{
BtnTxt = button1.Text;
UserControl1Event(this, e);
}
}
The problem is that both of your classes depend on each other.
Form1, when created, creates an instance of UserControl1, which in turn creates and instance of Form1, and so on. All this chained creation eventually makes your code throw a StackOverflowException.
It's expected behavior because of you are creating new Form1 instance and on object constructing it creates new UserControl1 instance that also creates new Form1 instance and so on.
If you need to have an owner of UserControl1 inside its instance you can pass it to the UserControl1 constructor:
public partial class Form1 : Form
{
...
UserControl1 uc1;
public Form1()
{
InitializeComponent();
// creates new control and pass owner via constructor parameter
uc1 = new UserControl1(this);
Controls.Add(uc1);
uc1.Visible = true;
uc1.UserControl1Event += new EventHandler(Handleuc1);
}
...
}
public partial class UserControl1 : UserControl
{
Form1 frm1;
public UserControl1(Form1 owner)
{
// save user control owner passed from constructor parameter to local variable
frm1 = owner;
}
...
}
I have 2 forms. The second form is opened from a method in the first form and I wish to be able to update the textbox that exists within that second form.
Basically I have the following code:
private void sendAllButton_Click(object sender, EventArgs e)
{
SendConsoleGUI sendOutGUI = new SendConsoleGUI();
sendOutGUI.Show();
sendOutGUI.sendConsoleTextBox.Text = "Test";
}
When I press the button the second form (SendConsoleGUI form) opens but "Test" is never added to its textbox.
Am I doing something wrong here?
You need to use invoke method.
sendOutGUI.Invoke((MethodInvoker) delegate { sendOutGUI.sendConsoleTextBox.Text = "Test"; });
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void sendAllButton_Click(object sender, EventArgs e)
{
SendConsoleGUI sendOutGUI = new SendConsoleGUI("Test");
sendOutGUI.Show();
}
}
public partial class ChildForm : Form
{
public ChildForm(string str)
{
InitializeComponent();
sendConsoleTextBox.Text = str;
}
}
This will work for you if you only wish to update it when the ChildForm is initially created.
I have a UserControl, that contains a panel, the panel contains a picture box.
When I MouseMove over the Picture Box, I want to update a label on the MainForm.
I have a get/set method on the main form, but how do I use it?? thanks
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
public String MouseCords
{
get { return this.MouseCordsDisplayLabel.Text; }
set { this.MouseCordsDisplayLabel.Text = value; }
}
}
public partial class ScoreUserControl : UserControl
{
public ScoreUserControl()
{
InitializeComponent();
}
private void ScorePictureBox_MouseMove(object sender, MouseEventArgs e)
{
// MainForm.MouseCords("Hello"); //What goes here?
}
}
Actually it's possible to do in your case like:
((MainForm)this.ParentForm).MouseCords = "Some Value Here";
But the right way is with events like Felice Pollano mentinoed:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
this.myCustomControlInstanse.PicureBoxMouseMove += new EventHandler<StringEventArgs>(myCustomControlInstanse_PicureBoxMouseMove);
}
private void myCustomControlInstanse_PicureBoxMouseMove(object sender, StringEventArgs e)
{
this.MouseCordsDisplayLabel = e.Value // here is your value
}
}
public class StringEventArgs : EventArgs
{
public string Value { get; set; }
}
public partial class ScoreUserControl : UserControl
{
public event EventHandler<StringEventArgs> PicureBoxMouseMove;
public void OnPicureBoxMouseMove(String value)
{
if (this.PicureBoxMouseMove != null)
this.PicureBoxMouseMove(this, new StringEventArgs { Value = value });
}
public ScoreUserControl()
{
InitializeComponent();
}
private void ScorePictureBox_MouseMove(object sender, MouseEventArgs e)
{
this.OnPicureBoxMouseMove("Some Text Here");
}
}
Ideally, you should raise an event for the same.
Create a delegate
public delegate void Update();
in the user control
public class MyUserControl : UserControl
{
public event Update OnUpdate;
}
On the main form register a handler for the user controls event.
public class Main
{
public Main()
{
myUserControl.OnUpdate += new Update(this.UpdateHandler);
}
void UpdateHandler()
{
//you can set the delegate with sm arguments
//set a property here
}
}
On user control,
To raise an event on button click
do this
OnUpdate();
This might give you an idea...
public partial class ScoreUserControl : UserControl
{
public ScoreUserControl()
{
InitializeComponent();
}
private void ScorePictureBox_MouseMove(object sender, MouseEventArgs e)
{
// MainForm.MouseCords("Hello"); //What goes here?
MainForm parent = this.ParentForm as MainForm;
if (parent != null) parent.MouseCordsDisplayLabel.Text = "Hello";
}
}
You have several options:
Create an event on the user control and have to form listen to it (I think this is the recommended way by most C# programmers).
Pass a reference to the main form to the User Control (in the constructor). This way, the user control knows about its MainForm.
Cast this.ParentForm to the MainForm class, then you have the reference.
Options 2 and 3 are somewhat more comfortable and lazy, but the cost is that the user control has to know about the specific class MainForm. The first option has the advantage that you could reuse the user control in another project, because it does not know about the MainForm class.
You should publish an event from the user control and subscribe to it from the main form.
At least this is the pattern suggested for winform. In any case the idea is to make the control "observable" from the agents who need to see the coords, instead of using it as a driver to update the interested agents.
In a parent form A, there's the following code to call a child form "B":
Window frmChildB;
frmChildB = new FormB();
frmChildB.ShowDialog();
In the same form: the following code to call a child form "C":
Window frmChildC;
frmChildC = new FormC();
frmChildC.ShowDialog();
Now I want to make a button in form B, so that if I click that button, it automatically navigate to form C.
Using a reference object of form C in form B like in the answer of this question should be avoided if possible. The reason is that there are more than ten forms like B, C... and each of them must be able to navigate to another. Having 10 form-referenced objects inside a form isn't good.
I think there must be some way to achieve the effect. Does anyone know about this?
If I understand your question correctly, you would like to have a single instance of each of the forms and just navigate back and forth between them.
If this is what you want, you can implement a static FormManager class that creates instances of the forms and shows them as needed. You can even use an enum to further reduce the complexity.
Here is an example of this class (it will need some additional work, but should give you a good idea):
public class FormManager
{
private static FormB m_FormB;
public static FormB formB
{
get
{
if (m_FormB == null)
{
m_FormB = new FormB();
}
return m_FormB;
}
}
private static FormC m_FormC;
puClic static FormC formC
{
get
{
if (m_FormC == null)
{
m_FormC = new FormC();
}
return m_FormC;
}
}
public enum FormId
{
FormB,
FormC
}
public static Form ShowForm(FormId whichForm)
{
Form oForm;
switch (whichForm)
{
case FormId.FormB:
oForm = FormManager.formB;
break;
case FormId.FormC:
oForm = FormManager.formC;
break;
default:
oForm = null;
break;
}
if (oForm != null)
{
oForm.ShowDialog();
}
return oForm;
}
}
This can be called from the child forms as:
FormManager.ShowForm(FormManager.FormId.FormB);
Try creating an Event in frmChildB and Subscribe to it in the Parent. You can then do what you want without having an reference to frmChildC in frmChildB.
Look at this MSDN link;
This is very rough but should give you an idea.
creating the event in the child forms
public delegate void SwapEventHandler(object sender, EventArgs e);
public partial class Form2 : Form
{
public event SwapEventHandler Swap;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Swap(sender, e);
}
}
Consumming it in the Parent Form
private void button1_Click(object sender, EventArgs e)
{
frmChildB = new Form2();
frmChildB.Name = "frmChildB";
frmChildB.Swap += new SwapEventHandler(frmChildB_Swap);
frmChildB.ShowDialog();
}
private void frmChildB_Swap(object sender, EventArgs e)
{
frmChildB.Swap -= new SwapEventHandler(frmChildB_Swap);
frmChildB.Close();
frmChildB.Dispose();
frmChildB = null;
frmChildC = new Form2();
frmChildC.Name = "frmChildC";
frmChildC.Swap += new SwapEventHandler(frmChildC_Swap);
frmChildC.ShowDialog();
}
void frmChildC_Swap(object sender, EventArgs e)
{
frmChildC.Swap -= new SwapEventHandler(frmChildC_Swap);
frmChildC.Close();
frmChildC.Dispose();
frmChildC = null;
frmChildB = new Form2();
frmChildB.Name = "frmChildC";
frmChildB.Swap += new SwapEventHandler(frmChildB_Swap);
frmChildB.ShowDialog();
}
At a primitive level it appears that you would benefit more from using the standard 'Wizard' pattern than having separate forms for each question. The exception being that instead of just having the typical next and back buttons, you should have buttons to jump to any of the questions. Here is a good tutorial that will walk you through the normal steps of creating a wizard.