How to access buttons in other class from Form1.cs - c#

I have 9 buttons in Form1.Designer.cs and I want to access them in another class, Puzzle.cs because later on I need to modify button changes in model class. The code below is what I attempted.
private Button[,] buttons = new Button[3, 3]
{ { Form1.button1, Form1.button2, Form1.button3 },
{ Form1.button4, Form1.button5, Form1.button6 },
{ Form1.button7, Form1.button8, Form1.button9 } };
It fails as the modifier for buttons is not static. I changed them into static type but this causes errors for buttons.
Can anyone give some advice?

You need a reference to an instance of the Form1 class. If it were called form, you could then access the button like form.button1.
But I'm not sure accessing buttons of the form from another class is a good design.

To get things compiling correctly, you'll need to make the following changes:
public partial class Puzzle : Form
{
private Button[,] buttons;
public Puzzle(Form1 form1)
{
buttons = new Button[,]
{
{ form1.Button1, form1.Button2, form1.Button3, },
{ form1.Button4, form1.Button5, form1.Button6, },
{ form1.Button7, form1.Button8, form1.Button9, },
}
};
}
The idea here is that Form1 is a class, not an instance of a class... A class is like a blueprint of a house, and a house is like an instance of that blueprint.
To get furniture out of the house, you first must instantiate and initialize that house (build, if you will), and then access the house's furniture instances.
In this case, you'll need to instantiate a new Form1, and pass that to the Puzzle form's constructor.
Form1 myForm = new Form1();
Puzzle myPuzzle = new Puzzle(myForm);
Puzzle will now be able to access that instance of Form1's buttons.
Note:
You can find the Program's instance of Form1 by looking in the Program.cs file of your solution.

Related

C# Specific value passing between forms without new instance

I have a C# application that allows the user to log certain events that occur in a game. For simplicity I'll call them ParentForm and ChildForm.
ParentForm is used 99% of the time, to log common events. This is represented as the user clicking a PictureBox and the Tag property of that PictureBox being added to a ListBox. When a "rare" event occurs, the user can click a "log rare event" button on ParentForm to open ChildForm which opens a set of "rare event" PictureBoxes, which function the same as in the ParentForm. The challenge is that I want these common and rare events to be logged to the same ListBox, so I am trying to find out how I would get a PictureBox click (and subsequent Tag from this PictureBox) on the ChildForm to the ListBox on the ParentForm.
The ParentForm does not close while ChildForm is open, and needs to stay open.
In the ParentForm code, I already have the code needed to capture one of the PictureBox clicks and grabbing the Tag, as well as handling dealing with adding it to the ListBox, so it'd be nice if I could just use these.
Here's what I've tried so far for the Parent:
// This file is EventLogger.cs
using rareEvent;
namespace mainWindow {
public partial class EventLogger : Form {
// In the ParentForm (listeners for PictureBox clicks are handled elsewhere)
public void pictureBox_Click(object sender, EventArgs e) {
PictureBox pbSender = (PictureBox) sender;
// Open new window and handle "rare" drops
if (pbSender.Tag.ToString() == "rare") {
// Open rare form
EventLogger.RareForm rare = new EventLogger.RareForm();
rare.Show();
}
}
}
}
and here's the child:
// This file is Rare.cs
using EventLogger;
namespace rareEvent {
public partial class rareEventForm : Form {
// In the ChildForm
private void pictureBox_Click(object sender, EventArgs e) {
// Does not compile if form is not instantiated, but I do not
// want a new instance
EventLogger form;
form.pictureBox_Click(sender, e);
}
}
}
I figured something like this would work, but it gives the error
The type or namespace name 'EventLogger' does not exist in the namespace
'mainWindow' (are you missing an assembly reference?)
Any help would be much appreciated. All the other examples I've found of value passing between forms all seem to create new instances which I don't want or were 8 years old and didn't work.
Appreciate it!
Edit: Code updated to have using <namespace> in each file. The problem still exists of not being able to send values between both forms without using new. (See comment to this answer)
In the first form create an instance (of it) here like my form1. It must be static and all datatypes you want to access should be public.
//FORM1
public partial class Form1 : Form
{
//Instance of this form
public static Form1 instance;
//For testing
public string myProperty = "TEST";
//Assign instance to this either in the constructor on on load like this
public Form1()
{
InitializeComponent();
instance = this;
}
//or
private void Form1_Load(object sender, EventArgs e)
{
//Assign the instance to this class
instance = this;
}
Then in form2 when calling EventLogger.RareForm rare = new EventLogger.RareForm(); instead of new form do
EventLogger.RareForm rare = EventLogger.RareForm.instance
Or in my case
Form1 frm = Form1.instance;
I then check the property of form 1 FROM form2 like so
Console.WriteLine(frm.myProperty);
Output was "Test"
Any trouble shout.

Passing tabConrol properties from on form to another

I am using two forms in a windows form application in C#.I want to pass the tabControl's properties like its "Tabpage count" from first form to second form. Can anyone help me here?I can't create object of first form in second form and call a function beacuse for a new forn object, the tabcontrol gets refreshed.
Inside your first form create an instance of your second Form class as this
Form frm= the instance of your secand form
after that show the instance of your secand form, now you exactly have an instance of your secand form inside your first form and can use all the public properties of it
You can create static public functions exposing desired control properties like in below code.
public static Color TabColor()
{
return Form1.Fom1TabControl1.SelectedTab.ForeColor;
}
and you can access Form1 properties like below;
private void Form2_Load(object sender, EventArgs e)
{
this.Fom2TabControl1.SelectedTab.ForeColor = Form1.ForeColor;
}
First Check your class accessibility and set to public if not work set public static, maybe your namespaces is different
hope it helps
This can be achieved in two ways
Aprroach 1:
Create a public variable in Form2
public int intTabCount=0;
and in Form1, you should call Form2 like
Form2 objForm2 = new Form2();
objForm2.intTabCount = tabPageCountVariable;
objForm2.Show()
Aprroach 2:
Create a parameterized constructor and public variable in Form2
public int intTabCount=0;
public Form2(int TabCounts)
{
intTabCount = TabCounts; // and use intTabCount for your class
}
and call from Form1 like
Form2 objForm2 = new Form2(tabPageCountVariable);
objForm2.Show();
Now if you want to pass value through any events like clicking an button in Form1 which updates anything in Form2, use the below link
Passing Values Between Windows Forms c#

Fill a list of objects from another class

I know this is a basic question, but I am struggling with it for quite some time now..
I have a main form in which I have a List<Filenames> and I have another class that gets invoked by the main form. This class has to insert some entries in my List<Filenames>.
In main form, I have the list initialized as:
public List<Filenames> filenamesList = new List<Filenames>();
And in the other class I do:
MainForm mainForm = new MainForm();
mainForm.filenamesList.Clear();
//then I have a for loop in which I perform some changes
mainForm.filenamesList.Add(new Filenames { name = "filename1", id = 1 } );
//it works until here and a new Filenames is added to the list
//then we go back to the main form
The problem is that now the List<Filenames> is empty. What am I doing wrong?
I have another class that gets invoked by the main form
I suspect the problem is here:
MainForm mainForm = new MainForm();
This creates a new MainForm instance, which is not the same instance as the MainForm that invokes the function.
I would redesign this so that the function you are invoking returns a List<Filenames> (or just an IEnumerable<Filenames> to be less specific) and let the form class worry about filling its filenamesList property. Exposing data members of a form can get messy quickly since you need to pass an instance of the form to anything that must use the property.
soimething like this:
-- other class --
public IEnumerable<Filenames> GetFilenames()
{
return new List<Filenames> { new Filenames { name = "filename1", id = 1 } };
}
--MainForm--
this.filenamesList.Clear();
this.filenamesList.AddRange(otherclass.GetFilenames());
When you do this in the second form:
MainForm mainForm = new MainForm();
You've created an entirely new instance of MainForm that has no reference to the list in the original MainForm instance. You're clearing the list and adding items to it, but when you exit your second form those items are lost.
You've got to pass your original MainForm instance to the new form that opens:
public class Form2 : Form
{
private MainForm mainForm;
public Form2(MainForm mainForm)
{
this.mainForm = mainForm;
}
public void SomeMethodThatUpdatesFileNamesList()
{
mainForm.filenamesList.Clear();
...
}
}
By declaring a new MainForm using the line MainForm mainForm = new MainForm(); you are not referring to the same filenamesList. You need to get the reference to the first class, either by sending the filenamesList as a parameter to the function or by adding it as a propery in one of the classes.
If the "other class" is a child of the main form, you might be able to get a reference to the parent object, but this depends on the stucture of the program.

Best way to copy a comboBox from form1 to form2

First I set the modifier property to "Internal" of comboBox1 on form1.
I used the following code:
form1 f1 = new form1();
object[] obj = new object[f1.comboBox1.Items.Count];
f1.comboBox.Items.CopyTo(obj, 0);
comboBox2.Items.AddRange(obj);`
Is it the best way to do this?
PS: I couldn't make this: Best way to access a control on another form in Windows Forms? to work.
PPS: Making controls is public is not what I like and neither preferred.
If you are wanting two drop-down lists with the same items in them it is much better that you store those items somewhere common and build up both combo boxes from there.
e.g.
public class Context{
...
...
public List<Foo> FooItems {
get{...}
}
}
public class Form1 {
...
combobox.AddRange(this.context.FooItems);
...
}
public class Form2 {
...
combobox.AddRange(this.context.FooItems);
...
}
This way you prevent coupling between your different forms, and still have only one place where you derive the values that go into the list.

calling method of parent form in c#

i have opened a mainform and call a child form like
Form4 f = new Form4();
f.Owner = this;
f.Show(this);
in form4, user selects a text file, the contents of which are to be displayed in a textBox1 of mainform
i was trying something like
Owner.textBox1.Text = "file contents";
but it does'nt work
The best way to link different forms together is via events. Create an event in Form4 like FileSelected and then do something like this:
Form4 f = new Form4();
f.FileSelected += (owner, args) => {
textBox1.Text = args.FileName;
};
f.Show(this);
Besides this is really bad design, you need to make textBox1 a public member of your main form and cast f.Owner to the main form type.
Like:
Form4 f = new Form4();
f.Owner = this;
f.Show(this);
// Inside Form4
MainForm main = this.Owner as MainForm;
if (main != null) main.textBox1.Text...
A best practice would be to define yourself a property that would itself set the Text property of your private control. Here's an instance:
public partial class MainForm : Form {
public string ContentDescription {
set {
textBox1.Text = value.trim();
}
}
}
Then after, you'll be able to access this property through type-casting to your particular type:
public partial class SecondaryForm : Form {
public MainForm OwnerForm {
get {
return (MainForm)this.Owner;
}
}
public void someMethod() {
OwnerForm.ContentDescription = "file contents";
}
}
Remember that in C#, every Control is declared private. So, to access it, the best practice is to define a property that will grant you the required access to it. Making a member public is generally not a good idea, depending on what you're trying to achieve.
EDIT For the parse method, perhaps should you consider making it public or internal so that you may access it through the correctly type-casted Owner property of your child form.
Making a hlper class might be the right solution though, so it is not GUI dependent.
In Form4 you can cast Owner to the correct type:
var o = (Form1) this.Owner;
o.textBox1.Text = "file contents";
For this to work, the owner must be of type Form1 and textBox1 on that type must be a public member or property.
As Andrew already gave the correct solution for event driven, there is also a sync (or blocking) method available:
Form4 f = new Form4;
if(f.ShowDialog() == DialogResult.OK)
{
textBox1.Text = f.FileName;
}
You will need to set the "modifiers" to at least public for the properties of the control to be able to have access to it.
alt text http://gabecalabro.com/gabe/Capture.PNG

Categories

Resources