C#/.NET Windows Forms Application - Event Handling [duplicate] - c#

I have a multiple forms in my project. Form1 contains a pictureBox that displays a jpeg. In Form2 I have a trackBar that I would like to control the zoom level of the image in Form1. To keep it simple I only need 2 or 3 zoom levels. I've set the pictureBox to public in the Designer view. However, when I try to reference the pictureBox in Form2 it says it doesn't exist. Below is the code I'm using to call Form2 in Form1
Form2 dataWindow = new Form2();
dataWindow.ShowDialog();
So in short the two things I need help with is:
1) Changing the properties of pictureBox1 from a separate form.
2) Creating a simple Zoom Formula.

It's considered bad design to allow other classes to modify the internal controls of the form. The form should be responsible for all of it's components. You shouldn't ever make any of the internal controls public. It's also considered bad practice for a child form to have a reference to the parent form.
The appropriate way to approach this problem is through events. The child form, Form2, should define a public event:
public event Action<int> TrackBarMoved;
Form2 can fire that event when the track bar is moved and pass, as the parameter, the position of the trackbar (if it makes sense to pass something else, such as the zoom level, or whatever else you want, that's fine too).
Form1 can the subscribe to that event when it creates From2 and change the zoom on the picture (internally, from within Form1) based on what the trackbar position is.

1) Pass a form1 reference into form2's constructor:
Form2 dataWindow = new Form2(this);
dataWindow.Show();
...
private form1 as Form1;
public Form2(Form1 frm1)
{
form1 = frm1;
}
Then in Form2s TrackBar_Scroll event reference the PictureBox via the private member variable form1: form1.PictureBox1.Property
2) Magnify your pictures using a PictureBox so that you can zoom with the Mouse Wheel
The better way is events:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var form2 = new Form2();
form2.TrackBarMoved += new Action<int>(ZoomPictureBox);
form2.ShowDialog();
form2.TrackBarMoved -= new Action<int>(ZoomPictureBox);
}
private void ZoomPictureBox(int zoomFactor)
{
pictureBox1.Width = 100 * zoomFactor;
pictureBox1.Height = 100 * zoomFactor;
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public event Action<int> TrackBarMoved;
private void trackBar1_Scroll(object sender, EventArgs e)
{
TrackBarMoved(trackBar1.Value);
}
}

Related

How to make form2 update when value changed in form1

In C# I have two forms "Form1" and "Form2". Form1 creates images that are stored in a folder. Form2 displays the number of images in that folder.
Say I have made 2 images with Form1 and then I open Form2. Form2 now says there are 2 images. Now while keeping both forms open I want to be able to add a new image and Form2 updates. At the moment if I use Form1 to add more images while Form2 is open Form2 continues to display the number of images that were in the folder when Form2 opened.
I have found solutions that involve Form2 closing and reopening but I don't want this. It's jarring for the user having windows opening and closing every time they press a button. I just want Form2 to update live as I make changes with Form1.
Any help would be greatly appreciated!! Thanks!
You can do this with public method in Form2
In Form1 you need to save Form2 object in property
FORM 1
public partial class Form1 : Form
{
public Form2 MyProperty { get; set; }
public Form1()
{
InitializeComponent();
}
// for opening form 2
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
MyProperty = f2;
}
// adding new image
private void button_ADD_Click(object sender, EventArgs e)
{
MyProperty.updateCounter();
}
}
When you add new image, then you can call the metoh from Form2 to update counter.
In FORM 2 you need crate PUBLIC method to update counter
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
// default value
label1.Text = "0";
}
// update counter
public void updateCounter()
{
label1.Text = (int.Parse(label1.Text) + 1).ToString();
}
}
You may want to take a look at events and delegates. Basically, whenever you do something to Form1 that can affect other forms, you want to trigger an event. In Form2, you have a method which you call whenever that event triggers. This way you can have multiple forms open, and as long as you set them to "listen" to a given event, they can all react.
You can read more about them here, in the Microsoft Documentation.

How to manipulate label of form2 in form3

I am trying to have a button in Form3 change a label's text in Form1 and Form2.
I have gotten it to work somewhat but in order to have the label change I have to have the mouse click on it. This is my current code in form 1 and 2:
label1.Text = Form3.myNameClass.myName;
and this is code in form 3
public class tournamentNameClass
{
public static string tournamentName;
}
public void button1_Click(object sender, EventArgs e)
{
myNameClass.myName = textBox3.Text;
}
How can I make it so that I dont need to press the label to get it to change?
Since you are at the start of learning, I'm not going to go in events and delegates.
My example demonstrates how you manipulate a control on Form1 from Form2 directly. You should be able to figure this out for Form3 easily by yourself, and is together a good practice of understanding.
(I want to state that there are many different methods/techniques for passing data or manipulate controls between forms, I guess this is the easiest one for you to understand as a beginner, as this is the most simplistic approach of all)
Form1 Designer
First we make label1 its modifier to Public (so we can reach it in another class) in the designer like so:
Form1 code behind
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// With the keyword "this" we pass in Form1, the current instance we are in
Form2 form2 = new Form2(this);
form2.Show();
}
}
Form2 code behind
public partial class Form2 : Form
{
private Form1 _form1;
public Form2(Form1 form1)
{
_form1 = form1;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
_form1.label1.Text = "lets change the text";
}
}
We are passing Form1 completely in the constructor, this could easily be the label1 control alone.
Result
I think you only need to trigger a redraw on forms 1 and 2.
after you set the text of the label, try calling labelControl.Refresh()
Or you could call refresh on form1 and form2 if that's any easier (that is a bit heavy handed though)
This will instruct the forms to redraw their visual representation based on how the data is set in the form currently.
Update:
You will need to invert your logic somewhat..
Rather than having a reverence to form 3 from form 1 and form 2, you will need to have a reference to form 1 and 2 from form3.. (woah so many form)
So then your button click method would look like this
public void button1_Click(object sender, EventArgs e)
{
form1.label1.Text = textBox3.Text;
form2.label1.Text = textBox3.Text;
form1.label1.Refresh();
form2.label1.Refresh();
}

Visible Property of Picture box not working from another form in C#

Hi I am using windows forms in C#. I am trying to modify the visible property of a picture from main form to another. Initially, the visible property of the picture box is set to false. On a button click from another form, the visible property of the picture box is modified to true.
This is the code written in the Form2 method:
private void button_Click(object sender, EventArgs e)
{
public Form1 frm1 = new Form1();
frm1.pictureBox.Visible= true;
}
Form1 is an instance type, so when you do
public Form1 frm1 = new Form1();
frm1.pictureBox.Visible= true;
you're really just creating a new instance of Form1 completely unrelated from your original Form1, changing a picture-box's visible property on it, and then discarding it.
What you can do, is put a reference to the "parent" Form1 inside your Form2 class.
Here's an example
public partial class Form2 : Form
{
public Form2(Form1 parent)
{
InitializeComponent();
this.Parent = parent;
}
Form1 Parent;
private void button1_Click(object sender, EventArgs e)
{
Parent.pictureBox.Visible= true;
}
...
}
there you create an instance of a form :
public Form1 frm1 = new Form1();
This is then obviously NOT the form you already may have in your page, which you could simply access by its ID.
According to your written code it will create new instance of the desired form, and NOT take the existing open form. Hence to identify the existing open form containing target picture box you need the target form and controlling form be related by like Parent form or MDI Parent Form.
Assuming case of MDI Parent Form (i.e. Controlling form is MDI Parent of Target Form), you need following codes to identify to existing open form:
foreach (Form frm in MdiChildren)
{
if (frm is myTargetForm)
{
//do your code to find control using id of picture box and change the required properties
}
}

How do I refrence form1 from form2 without causing an infinite loop?

In my main form (form1) I have checkboxes that when checked should also check the corresponding box in form2. I also want if checkboxes in form2 are checked they check the corresponding boxes on form1. The problem that I believe I am encountering is that form1 can make an object of form2 to reference, however if I instantiate an object of form1 within form2 I believe it creates an infinite loop? Any help figuring this out is appreciated.
Form1 creates an object of form2:
Form2 formSettings = new Form2();
Now when I have an event I can update form2:
public void logScanResultsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (logScanResultsToolStripMenuItem.Checked)
{
formSettings.chbxLogScanResults.Checked = true;
}
else
{
formSettings.chbxLogScanResults.Checked = false;
}
}
But if I try to do something similar in Form2:
Form1 form1 = new Form1();
So that I can reference form1's menu item from within form2(formSettings) I end up creating an object (form1) that calls to make an object of Form1, which within Form1 includes a call to create an object of Form2 and thus an endless loop.
You shouldn't create an instance every time a checkbox is checked off. You need to maintain the instances alive and hide/show them as needed. Also, the constructor of one of the forms should receive the other one as parameter in its constructor so they can reference each other.
Hopefully this is clear enough. It isn't a straight out answer as you really dont have much detail in your question.
Basically you have two forms, Form1 and Form2, which will be throwing events (OnChangeEvent?) on the change of some checkboxes.
Form1 listens for events from Form2 and Form2 does the same from Form1.
If Form1's event listen receives a OnChangeEvent and changes its checkbox then it should raise an OnChangeEvent. If on the other hand it doesn't change its checkbox (as it already has the correct value) then it should not raise an OnChangeEvent.
In the body of Form1 you need to declare Form2 to hold an instance of it for referencing and to open it. When you call the Form2.Show method from Form1, you will pass a reference of itself to Form2 which you then can use to gain access back to Form1.
public partial class Form1 : Form
{
Form2 form2 = new Form2();
public Form1()
{
InitializeComponent();
}
private void form1Button_Click(object sender, EventArgs e)
{
form2.Show(this);
}
private void form1CheckBox_CheckedChanged(object sender, EventArgs e)
{
form2.ChangeCheck(form1CheckBox.Checked);
}
public void ChangeCheck(bool isItChecked)
{
form1CheckBox.Checked = isItChecked;
}
}
In Form2 you can now reference Form1 as the owner.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void form2CheckBox_CheckedChanged(object sender, EventArgs e)
{
((Form1)this.Owner).ChangeCheck(form2CheckBox.Checked);
}
public void ChangeCheck(bool isItChecked)
{
form2CheckBox.Checked = isItChecked;
}
}

How can I Change something in a Form1 from a DialogBox?

Lets say I have two forms ( Form1 And Form2 ).
Form1 has a PictureBox
Form2 I has an OpenFileDialog
Form1 is the main form, so when I run the project I see Form1.
How can I change the Image in the PictureBox in Form1 from Form2?
How do I pass a value from a child back to the parent form?
Basically, expose the value that gets returned in the open file dialog with some property and let the parent form grab it.
In the Program.cs file you can set any value, either FormOptions to the form's instance .
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var frm = new Form1();
// Add the code to set the picturebox image url
Application.Run(frm);
}
In addition you can add the Constructor to Form1 and pass the parameter via constructor.
Pass one form as a parameter to a constructor of the second form or add a method that passed the reference. After you have the reference to your form you can do whatever you want with the from.
Whether to share picture box as a public member is up to you. However, I would suggest making a public method SetImage() in the first form. Second form would call form1.SetImage().
[Update]
Wait, why do you need to set image from OpenFileDialog, you just need receive fileName from the dialog, and then open the file and load into the form.
Like this:
private void button1_Click(object sender, EventArgs e)
{
using (var dialog = new OpenFileDialog())
{
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
pictureBox1.Image = Image.FromFile(dialog.FileName);
}
}
This is code inside of Form1.
[Update]
Here is the basic idea how to access one form from another.
public class MyForm1 : Form
{
public MyForm1()
{
InitializeComponent();
}
public void SetImage(Image image)
{
pictureBox1.Image = image;
}
private void button1_Click(object sender, EventArgs e)
{
var form2 = new Form2(this);
form2.Show();
}
}
public class MyForm2 : Form
{
private MyForm1 form1;
public MyForm2()
{
InitializeComponent();
}
public MyForm2(MyForm1 form1)
{
this.form1 = form1;
}
private void button1_Click(object sender, EventArgs e)
{
form1.SetImage(yourImage);
}
}
You can very simply do this.
At first change your code(in Form1) that show Form2 to looks like this:
<variable-of-type-Form2>.ShowDialog(this);
or if you dont want form2 to be modal
<variable-of-type-Form2>.Show(this);
Next when you got path to image, you can access pictureBox like this
((PictureBox)this.Owner.Controls["pictureBox1"]).Image=Image.FromFile(<filename>);
Assume that you have PictureBox on Form1 with name "pictureBox1"
Ideally, you want to structure your code in a ModelViewController pattern. Then, you simply have a reference in your model to the image in the picture box. When interacting with the OpenFileDialog in Form2, you would call your model adapter interfaces hooked into the views (Form1 and Form2) to change the image being held in the model. In short, you need a callback from the view to the model. If you don't want to redesign your code to be MVC, simply have a shared object holding the image reference that both Form1 and Form2 receive in their constructors, so they can both modify it.

Categories