Access to creator object - c#

I have a simple windows application in C# with 3 forms.
first form is main form (its name is FrmMain), second is FrmData and third is FrmShow.
In main form (FrmMain) I have created an instance from second form (FrmData) and show it :
public partial class FrmMain : Form
{
public Form FrmModifyData; //for FrmData
int PersonCode;
public FrmMain()
{
InitializeComponent();
}
private void btnShowDataForm_Click(object sender, EventArgs e)
{
FrmModifyData= new FrmData();
FrmModifyData.ShowDialog();
}
}
but I can't access from FrmModifyData to FrmMain fields like PersonCode .
How can I access to creator object's field?
Note: I'm a beginner.
thanks.

You would need to add a property to your FrmModifyData class to take an instance of the FrmMain class. Then you can do this:
FrmModifyData = new FrmData();
FrmModifyData.ParentData = this;
FrmModifyData.ShowDialog();
Then inside FrmModifyData you would have access to the public members of FrmMain. Obviously this is kind of quick and dirty and not very reusable so i would suggest adding more explicit properties to FrmModifyData with only the data you need to use.

If you want to access PersonCode field, you should declare it as public. No visibility modifier will make it private, hence not accesible from other casses.

I would make it something like this.
With this way you're able to use the FrmModifyData in other forms.
I know it's an old post, but yes, you did read it :)
public partial class FrmMain : Form
{
// public Form FrmModifyData; <-- do not declare it in your FrmMain
// (is't a modal dialog, so you won't get more instances)
public int PersonCode {get; set;}
public FrmMain()
{
InitializeComponent();
}
private void btnShowDataForm_Click(object sender, EventArgs e)
{
FrmData FrmModifyData = new FrmData();
FrmModifyData.PersonCode = this.PersonCode;
DialogResult result = FrmModifyData.ShowDialog();
if(result == DialogResult.Ok)
{
// do something with the result
this.PersonCode = FrmModifyData.PersonCode;
}
}
}

Related

Why I can't Invoke from a different class?

My problem is, I can't invoke a message into the TextBox and I can't understand why.
There is a main class and a second class, both with call to the other one.
Where is my error?
using System;
using System.Windows.Forms;
namespace Class_Test___Invoke
{
public partial class MAINFORM : Form
{
public MAINFORM()
{
InitializeComponent();
_INVOKER = this;
}
private MAINFORM _INVOKER;
private static CLASS _CLASS = new CLASS();
private void button1_Click(object sender, EventArgs e)
{
_CLASS._MESSENGER();
}
public void _LOGGING(string _MESSAGE)
{
if (InvokeRequired)
{
_INVOKER.Invoke(new Action<string>(_LOGGING), new object[] { _MESSAGE });
textBox_ausgabe.AppendText(_MESSAGE);
return;
}
else textBox_ausgabe.AppendText(_MESSAGE);
}
}
}
namespace Class_Test___Invoke
{
class CLASS
{
private MAINFORM _MAINFORM = new MAINFORM();
public void _MESSENGER()
{
_MAINFORM._LOGGING("Test");
}
}
}
You are assuming that the _MAINFORM you create in the CLASS constructor is the same instance as the form where the button was clicked, which is not the case. You have a chicken-and-egg problem. Your form creates a CLASS, and the CLASS creates a form. So now you have two different forms. (or two different CLASS instances since you don't show how the first form or CLASS is created)
You need to "connect" the form and the class, either by passing the form to the constructor as a parameter or by some other means.
Finally, I would encourage you to do some research on best practices for class and member names. It's a bit disconcerting for a seasoned C# developer to see names in all caps and prefaced by underscores.

C# Creating a global object of a class for use on multiple forms

I want to create a multiple objects of a class, edit them on one form and then use those objects on multiple forms. Hopefully the code below will try and highlight the problem.
I created a class as such...
public class Player
{
public string name;
public int goals;
}
On Form1 I have created tom and dan, and added buttons that will increase their goal count when pressed.
public partial class Form1 : Form
{
Player tom = new Player()
{
name = "Tom",
goals = 5
};
Player dan = new Player()
{
name = "Dan",
goals = 7
};
public void UpdateForm()
{
label1.Text = tom.name;
label2.Text = dan.name;
}
public Form1()
{
InitializeComponent();
UpdateForm();
}
private void button1_Click(object sender, EventArgs e)
{
tom.goals += 1;
}
private void button2_Click(object sender, EventArgs e)
{
dan.goals += 1;
}
}
I then want to be able to display their names and the new number of goals on form2. The problem I have is that those objects don't exist in that context.
{
public partial class Form2 : Form
{
public void UpdateForm2()
{
label1.Text = tom.name;
label2.Text = tom.goals;
label3.Text = dan.name;
label4.Text = dan.goals;
}
public Form2()
{
InitializeComponent();
UpdateForm2();
}
}
}
How do I make those objects global and editable between forms? I've tried to find an answer but haven't found one that quite matches this use case. I would appreciate any help and advice.
Your Form1 class is like any other class. Therefore, you can create 2 properties in it:
public partial class Form1 : Form
{
public Player Tom { get; private set; }
public Player Dan { get; private set; }
this.Tom = new Player()
{
name = "Tom",
goals = 5
};
this.Dan = new Player()
{
name = "Dan",
goals = 7
};
// The rest of your code
}
In Form2 introduce a property:
public partial class Form2 : Form
{
public Form1 CallingForm {get; set;}
public Form2()
{
InitializeComponent();
UpdateForm2();
}
}
Set that property before you show the second form like this (put this code in your first form):
Form2 f2 = new Form2();
f2.CallingForm = this;
Then in the second form you can access the players like this:
label1.Text = CallingForm.Tom.name;
If you have more players then create a List<Player> property instead.
Some other notes
Try following the .NET naming conventions and instead of public fields, use properties. Properties can be used for databinding and encapsulation, validation and has other benefits as well.
public class Player
{
private int goals;
public string Name {get; set;}
public int Goals
{
get { return this.goals; }
set
{
if (value < 0)
{
throw new ArgumentException("Goals cannot be less than 0.");
}
this.goals = value;
}
}
}
You need to know the concept of namespace. If you create an object in namespace of one form, you cannot use that particular object without referring that particular form.
So far what I can see, you've created two instances of object player in form namespace. But that's not there in form2 namespace. Hence you're getting that error.
You can use many methods commonly used to update such as
calling child window's method to update the values.
using mediator
adding an event listener to form2 on value change.
Using a global instance of an object instance or a static object is not a best practice.
You can pass the list of players in the constructor of the second form.
Yes , must transport data new form. Meybe use
send parameter to Form2 contructor parameter or use form2 Set Method.
For Example :
private readonly Player _tom;
private readonly Player _dan;
public Form2(player tom, player dan) // or use List<Player> parameter
{
InitializeComponent();
_tom = tom;
_dan = dan;
}
another way
// Form2.cs
private Player _tom;
private Player _dan;
public void SetPalyers(Player tom, Player dan)
{
_tom = tom;
_dan = dan;
}
Think about encapsulation. Your Form2 cannot access the instantiated class objects because they are contained within Form1.
When you write the following:
label1.Text = tom.name;
The compiler is looking for the object Form2.tom, but it doesn't exist.
You have to tell it where to look, like so:
label1.Text = Form1.tom.name;
To make these objects available to all chosen classes without using the Form1 prefix, the chosen classes would have to be subclasses of Form1. Other than that, you'd have to refer back to them in the way I explained previously.
It seems like you need a service class that holds a List<Person>. Then just have your two forms share the same instance of that service. Or the lazy option is to make the service a static class.
Update
You could also consider implementing the Observer pattern in the service.
http://www.dofactory.com/net/observer-design-pattern

how to edit the primary form using a form that was created from the primary form in C#

I want to edit a primary form(Form1) using a form that is created from its code(Form2). The way I have done it is that, when the event is triggered, the new form appears, and everything works, but I want it so that when a button is pressed, the original form is edited. The code I have tried is this:
Form1 form1 = new Form1();
private void button1_Click(object sender, EventArgs e)
{
form1.startNewGame();
this.Hide();
}
By the way, I realise that this is creating a new instance of the form, I want to know how to edit the already existing instance of the form.
Without having the code of Form2 is hard to help you, but I will try. Instead of creating an instance of Form1, add a public property to form2
public Form1 PrimaryForm{get;set;} and when you showin form2 set that property to this
A solution would be to pass a reference of your Main Form to the child form when the child form is initialized. You can then set the value of the mainform through the reference. See below for an example:
public class ChildForm1 : Form
{
// Fields
private MainForm _mainForm;
private bool _value1;
private bool _value2;
// Default constructor
public ChildForm1()
{
}
// Overloaded constructor that accepts a container of values
public ChildForm1(ValuesContainer values, MainForm mainForm)
{
_mainForm = mainForm;
_value1 = values.Value1;
_value2 = values.Value2;
//Set a main form value
_mainForm.Value = "This value was changed by ChildForm1."
}
}
public class ChildForm2 : Form
{
// Field
private bool _value3;
// Default constructor
public ChildForm2()
{
}
// Overloaded constructor that accepts a container of values
public ChildForm2(ValuesContainer values)
{
_value3 = values.Value3;
}
}
public class MainForm : Form
{
public string Value { get; set; }
// Default constructor
public MainForm()
{
}
// Simulated - Event method called when button is clicked for child form 1
public void CallChildForm1()
{
ValuesContainer values = new ValuesContainer();
// Set the values from the main form
values.Value1 = true;
values.Value2 = true;
// Call the child form while passing in the container of values that we just populated.
ChildForm1 childForm = new ChildForm1(values);
childForm1.Show();
}
// Simulated - Event method called when button is clicked for child form 2
public void CallChildForm2()
{
ValuesContainer values = new ValuesContainer();
// Set the value from the main form
values.Value3 = true;
// Call the child form while passing in the container of values that we just populated.
ChildForm2 childForm = new ChildForm2(values);
childForm2.Show();
}
}
// Simple data object or container used to transfer information between complex objects such as forms and controls.
// These are also known as data classes or data transfer objects (DTOs)
public class ValuesContainer
{
public bool Value1 { get; set; }
public bool Value2 { get; set; }
public bool Value3 { get; set; }
}
This might not be the best practice but is the simplest way to do it. Here are the steps;
1) in Form1 add a public method to edit whatever you want
2) in Form2 add a reference to type Form1
3) instantiate Form2 and set InstanceOfForm2.ReferenceToForm1 = this;
4) in the event handler of Form2 use the reference to call your public method like
//inside some event handler
this.ReferenceToForm1.MyPublicMethodThatEditsTheDisplay();
One thing to remember is that Form1 is just an object like any other. The only thing preventing you from editing it anywhere you choose is the access level of it's properties (can't touch private fields, obviously) and the lack of reference. Everything beyond that is a matter of opinion and 'best practice' if you want to edit from anywhere, make the field public/provide a public method and pass/set a reference.

Accesing Richtextbox from a class

I'm trying to append text in my richtextbox which is called ConsoleText. It's not working very well. I'm using a property in my form to access the richtextbox in the Class.
It looks like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Skipped the rest
public string ACText
{
set
{
ConsoleText.AppendText(value);
}
}
Now from my class's constructor.
public McDonalds(string email, string pass)
{
Form1 f = new Form1();
f.ACText = "test";
}
It's not showing any text in my richtextbox sadly. I know it works, because i can in the property use a messageBox and see that the value is passed into it.
Thanks in advance i really need help with this.
Calling Form1 f = new Form1(); does not give you a reference to an existing form, it creates a new one with blank/default values in the form's controls.
HOW to solve this greatly depends on your design. If you want to tie your class to that form implementation, our class needs either a reference to the form, a reference to the control, or the value of the control that you're interested in passed to it.
For example:
public McDonalds(string email, string pass, Form1 form)
{
form.ACText = "test";
}
A cleaner solution would be to RETURN a value from your McDonalds class and let the FORM set the control value appropriately rather than tying your class to that form class.
you can use Singleton:
Singletons make having single instances easy. They allow for single allocations and instances of data. We review the singleton types. We see one of the fastest implementations. And we review other possibilities.
public partial class Form1 : Form
{
public static Form1 instance = null;
public Form1()
{
instance = this; //add this class to singleton
InitializeComponent();
}
public void Show(string Message)
{
MyConsole.Text = Message;
}
another class:
Form1.instance.Show("blah blah");
Create Delegate in Form1 Class binded method ACText (string val), and Pass the Delegate to McDonalds Class. Fire the Delegate
namespace YourNameSpace
{
public delegate void RichTextBoxDelegate(string text);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void ACText(string s)
{
ConsoleText.AppendText(s);
}
// In Some Method Call MCDonald's form
public void ShowMcDonalds()
{
RichTextBoxDelegate deleg = new RichTextBoxDelegate(ACText);
MCdonalds ob = new McDonalds(deleg);
ob.show();
}
}
}
Pass the deleg to McDonalds form
Just fire the Delagate
public McDonalds(RichTextBoxDelegate sp)
{
Form1 f = new Form1();
sp("This is Test");
}
deleg("Test value"); // form McDonald's Form

Multiple .cs files and access to Form

I'm trying to write my first program in C# without the use of a tutorial. To ensure that I adopt from the start good coding practices, I want to create each class in an different .cs file. However, I'm running into some troubles when trying to access the elements of the program in such an .cs file.
For example, I have an Form1.cs with an Label and a Start button. When clicking on the start button, a text should appear in the Label. So:
In Form1.cs I have:
namespace TestProgram
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void startButton_Click(object sender, EventArgs e)
{
WriteToLabel message = new WriteToLabel();
message.WelcomeMessage();
}
}
}
And in my separate WriteToLabel.cs file:
namespace TestProgram
{
public class WriteToLabel
{
public void WelcomeMessage()
{
Form1 myForm = new Form1();
//myForm.. --> myForm doesn't have an 'outputLabel'?
outputLabel.Text = "Welcome!"; // This returns an error: 'The name outputLabel does not exits in the current context'.
}
}
}
'outputLabel' is the (Name) I've given the label, and this is in accordance to the name in Form1.Designer.cs.
Both files are using the same components such as 'using System';.
However, from my WriteToLabel.cs file I can't seem to access the Form which holds my program. I did manage to succeed to create different .cs files in an Console Application, which only added to my confusion. So, I have two questions:
First, how can I access the Form from a separate class (i.e. not an partial class) in a separate file?
Second, is this the good way to do it, or is it inefficient to create multiple instances of different classes?
Any thoughts or ideas are highly welcome,
Regards,
The designer automatically creates controls as private fields, because of that your WriteToLabel class can't access it. You need to change that.
Also a good start would be to change the class to something like that:
namespace TestProgram
{
public class WriteToLabel
{
Form1 form;
public WriteToLabel(Form1 form)
{
this.form = form;
}
public void WelcomeMessage()
{
//Form1 myForm = new Form1();
//myForm.. --> myForm doesn't have an 'outputLabel'?
form.outputLabel.Text = "Welcome!";
}
}
}
You're actually instantiating a new instance of Form1, whereas you need to pass in a reference to your existing instance:
public void WelcomeMessage(Form1 form)
{
form.outputLabel.Text = "Welcome";
}
You also need to ensure that outputLabel is a public (or internal) property/field of Form1 so you can set the value accordingly. Then the calling code is slightly different:
private void startButton_Click(object sender, EventArgs e)
{
WriteToLabel message = new WriteToLabel();
message.WelcomeMessage(this);
}
You need to make sure that Form1.outputLabel has public or internal visibility.
You only need something like a LabelWriter class if the class is going to share a significant amount of state or private methods. If all you have is a bunch of methods that set properties on separate objects, you might as well just keep it as a method on the same object (in this case the Form1 object):
void startButton_Click(object sender, EventArgs e)
{
displayWelcomeMessage();
}
void displayWelcomeMessage()
{
this.outputLabel = "Welcome!";
}

Categories

Resources