Parameter passing an Object instead of entire Form - c#

I've created a simple Pokemon WinForm application with just 2 forms. Form1 shows the Pokemon and its associated values.
Upon Clicking the Edit button, Form2 appears (EditCharacter) allowing the user to edit the attributes of the character.
To get the selected Pokemon to appear in Form2 (EditCharacter), I've passed in the currentCharacter from Form1.
Here is the code for Form1.
public partial class Form1 : Form
{
CardCollection cardCollection;
public Character currentCharacter;
public Form1()
{
InitializeComponent();
cardCollection = new CardCollection();
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (var keyValuePair in cardCollection.Cards)
{
cmbPokemon.Items.Add(keyValuePair.Key);
}
}
private void cmbPokemon_SelectedIndexChanged(object sender, EventArgs e)
{
currentCharacter = cardCollection.Cards[cmbPokemon.Text];
updateControls();
}
public void updateControls()
{
lblHP.Text = currentCharacter.HealthPoints.ToString();
lblStrength.Text = currentCharacter.Strength.ToString();
lblSpecialPower.Text = currentCharacter.SpecialPower;
pbPokemon.ImageLocation = #currentCharacter.FileName;
}
private void btnEdit_Click(object sender, EventArgs e)
{
EditCharacter EditChar = new EditCharacter(currentCharacter);
EditChar.ShowDialog();
}
}
And here is the code with Constructor for the EditCharacter form:
public partial class EditCharacter : Form
{
Character currentCharacter;
public EditCharacter( Character c)
{
InitializeComponent();
currentCharacter = new Character();
currentCharacter = c;
lblCharacter.Text = c.Name;
pbCharacter.ImageLocation = c.FileName;
txtPower.Text = c.SpecialPower;
tbHP.Value = c.HealthPoints;
tbStrength.Value = c.Strength;
lblHP.Text = c.HealthPoints.ToString();
lblStrength.Text = c.Strength.ToString();
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
lblHP.Text = tbHP.Value.ToString();
}
private void tbPower_Scroll(object sender, EventArgs e)
{
lblStrength.Text = tbStrength.Value.ToString();
}
private void btnSave_Click(object sender, EventArgs e)
{
currentCharacter.Name = lblCharacter.Text;
currentCharacter.FileName = pbCharacter.ImageLocation;
currentCharacter.SpecialPower = txtPower.Text;
currentCharacter.HealthPoints = tbHP.Value;
currentCharacter.Strength = tbStrength.Value;
currentCharacter.SpecialPower = txtPower.Text;
this.Close();
}
}
My question is (and I've tried), how to preserve the values set in the EditForm to appear in Form1? For example, I edit Rayquaza's HealthPoints to 0, but when I return to Form1, it hasn't changed.

You can use interface to pass the same object directly to EditCharacter from and get it back when it has been updated.
Create new interface , that contains two methods one for reading and the other for writing.
public interface ICharacterManager
{
Character ReadCharacterData();
void WriteCharacterData(Character character);
}
Update your Form1 code by applying ICharacterManager interface, like this :
public partial class Form1 : Form , ICharacterManager
{
CardCollection cardCollection;
public Character currentCharacter;
public Form1()
{
InitializeComponent();
cardCollection = new CardCollection();
}
// The currentCharacter object which will be passed to EditCharacter form.
public Character ReadCharacterData()
{
return currentCharacter;
}
// Get back Character object from EditCharacter form after updating data and pressing Save Button
public WirteCharacterData(Character character)
{
currentCharacter = character;
// Call you updateControls() Method here.
updateControls();
}
private void btnEdit_Click(object sender, EventArgs e)
{
// You can still use this code, because already the type of Form1 is IChatacterManager now.
EditCharacter EditChar = new EditCharacter(this);
EditChar.ShowDialog();
}
}
Update your EditCharacter code by adding ICharacterManager variable like this :
public partial class EditCharacter : Form
{
private ICharacterManager _characterManager;
Character currentCharacter;
public EditCharacter(ICharacterManager characterManager)
{
InitializeComponent();
_characterManager = characterManager;
// Character object which come form Form1.
currentCharacter = _characterManager.ReadCharacterData();
lblCharacter.Text = currentCharacter.Name;
pbCharacter.ImageLocation = currentCharacter.FileName;
txtPower.Text = currentCharacter.SpecialPower;
tbHP.Value = currentCharacter.HealthPoints;
tbStrength.Value = currentCharacter.Strength;
lblHP.Text = currentCharacter.HealthPoints.ToString();
lblStrength.Text = currentCharacter.Strength.ToString();
}
private void btnSave_Click(object sender, EventArgs e)
{
currentCharacter.HealthPoints = tbHP.Value;
currentCharacter.Strength = tbStrength.Value;
currentCharacter.SpecialPower = txtPower.Text;
// Check if _characterManager object is not equal to null.
if (_characterManager != null)
{
// Pass the updated object back to Form1
_characterManager.WriteCharacterData(currentCharacter);
}
this.Close();
}
Hope this was helpful.
Happy coding :) ...

Related

C#-Winforms-How to use instance objects in different subforms?

I have a "MainForm" and a "GraphicsForm". Clicking "New" on the main form, a "GraphicsForm" will be created.
The problem is that when I create multiple "GraphicsForm", and when I want to save the content of one of the "GraphicsForm", I need to clicking "Save" on the "MainForm" and the program will save the content of the active "GraphicsForm" to a file, I don't know how to pass the content of this "GraphicsForm" to "MainForm" for storage.
MainForm.cs
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private ToolStripMenuItem _winMenuItem = new ToolStripMenuItem();
private GraphicsForm _graphicsForm;
private int _counter = 1;
private void New_Click(objec sender, EventArgs e)
{
_winMenuItem.Name = "Win";
_winMenuItem.Text = "Windows";
int item = MainMenuStrip.Items.IndexOf(_winMenuItem);
if (item == -1)
{
MainMenuStrip.Items.Add(_winMenuItem);
MainMenuStrip.MdiWindowListItem = _winMenuItem;
}
_graphicsForm = new GraphicsForm();
_graphicsForm.Name = string.Concat("Win_", _counter.ToString());
_graphicsForm.Text = _graphicsForm.Name;
_graphicsForm.MdiParent = this;
_graphicsForm.Show();
_graphicsForm.WindowState = FormWindowState.Maximized;
_counter++;
}
private void Save_Click(object sender, EventArgs e)
{
... // Problem here
}
private void Open_Click(object sender, EventArgs e)
{
... // Problem here
}
}
GraphicsForm.cs
public partial class GraphicsForm : Form
{
//StorageDoc is a class to manage all the graphics drawn by the user in the form.
private StorageDoc _storageDoc = new StotageDoc();
public GraphicsForm()
{
InitializeComponent();
}
private Canvas_MouseDown()
{
}
private Canvas_Paint()
{
}
...
Because MainForm is a MDI form, it is easy to use ActiveMdiChild to get the active child form.
class MainForm : Form
{
public void OnSaveButtonClick(object sender, EventArgs e)
{
if(ActiveMdiChild is GraphicsForm g)
Save(g);
}
}
I'm sure this has been answered before but basically, you pass in an instance of the 'data storage' to the new form.
interface ISaveForm
{
void Save();
}
class MainForm
{
private DataStorage _dataStorage;
private ICollection<ISaveForm> _forms = new List<ISaveForm>();
public void OnNew()
{
var subForm = new GraphicsForm(_dataStorage);
subForm.Show();
_forms.Add(subForm);
}
public void OnSave()
{
foreach(var form in _forms)
{
form.Save();
}
}
}
class GraphicsForm : Form,ISaveForm
{
private DataStorage _dataStorage;
public GraphicsForm(DataStorage dataStorage)
{
_dataStorage = dataStorage;
}
public void Save()
{
}
}

Struggling to add to ListBox

So I'm making this small program for my assignment at university and I'm finding it hard to add to my list in my form. Here is my code:
public partial class WorkOutBeam : Form
{
Check checkLib;
public BindingList<ListBox> list;
public WorkOutBeam()
{
InitializeComponent();
}
public void StartForm(object sender, EventArgs e)
{
list = new BindingList<ListBox>();
listBox1.DataSource = list;
}
private void NewForce_Click(object sender, EventArgs e)
{
NewForceName forceItem = new NewForceName();
forceItem.Show();
}
public void AddToForceList(string name)
{
list.Items.Add(name);
}
}
NewForceName class below:
public partial class NewForceName : Form
{
public WorkOutBeam workOutBeam;
public NewForceName()
{
InitializeComponent();
}
private void OkButton_Click(object sender, EventArgs e)
{
if (NewForceNames.Text != "")
{
ReferToLibs();
workOutBeam.AddToForceList(NewForceNames.Text);
Close();
}
}
private void ReferToLibs()
{
workOutBeam = new WorkOutBeam();
}
private void NewForceName_Load(object sender, EventArgs e)
{
}
}
So I say to my program, "give me a new force." When it does, it initializes a new form of "NewForceName." I type into a text box and click 'Ok', this starts a public method shown below:
The list is a binding list which refers to the listBox as a data source. However the program tells me that the Items part is inaccessible due to its protection but I don't know how to add it as public. I tried looking in the properties of my listBox but to no avail.
Give this a shot:
public partial class WorkOutBeam : Form
{
Check checkLib;
// public BindingList<ListBox> list; // get rid of this for now
public WorkOutBeam()
{
InitializeComponent();
}
/*public void StartForm(object sender, EventArgs e)
{
list = new BindingList<ListBox>();
listBox1.DataSource = list;
}*/
private void NewForce_Click(object sender, EventArgs e)
{
NewForceName forceItem = new NewForceName(this); // pass a reference to this
// instance of WorkoutBeam
forceItem.Show();
}
public void AddToForceList(string name)
{
// we should do some more things here, but let's keep it simple for now
listBox1.Items.Add(name);
}
}
And
public partial class NewForceName : Form
{
public WorkOutBeam workOutBeam;
public NewForceName( WorkoutBeam beam ) // we take a WorkoutBeam instance as CTOR param!
{
InitializeComponent();
workoutBeam = beam;
}
private void OkButton_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(NewForceNames.Text))
{
workOutBeam.AddToForceList(NewForceNames.Text);
Close();
}
}
// DO NOT create new WorkoutBeams every time. Use the original.
/*private void ReferToLibs()
{
workOutBeam = new WorkOutBeam();
}*/
}
Disclaimer: I did not address each and every problem in this code. This is just enough so that it should "work" as intended.

Accessing form1 variables from another class how?

how do I access form1 string variable from a different class?
public partial class Form1: Form
{
public Form1()
{
InitializeComponent();
}
public string deva = "123";
//button
private void button8_Click(object sender, EventArgs e)
{
deva = "456";
}
private void button9_Click(object sender, EventArgs e)
{
Other ks = new Other();
ks.test_me();
}
}
public class Other: Form1
{
//trying to access Form1 variable.
public void test_me()
{
Form1 fm = new Form1();
MessageBox.Show(fm.deva);
//deva is 123 but not 456.
//I clicked on button and values changes it form1 however from here it assigns just default value
}
//
//Does creating a new form1 will reset its values?
//Somebody please help me. how to solve this issue.
}
public partial class Form1: Form {
public Form1()
{
InitializeComponent();
}
public string deva = "123";
//button
private void button8_Click(object sender, EventArgs e)
{
deva = "456";
}
private void button9_Click(object sender, EventArgs e)
{
Other ks = new Other(this);
ks.test_me();
}
}
no need to inherit from form1, please pass the object via constructor
public class Other {
Form1 obj = null;
public Other(Form1 object)
{
this obj = object;
}
public void test_me()
{
MessageBox.Show(obj.deva);
}
}
Make your variable deva Static. Access it with Class directly not object.
public static string deva = "123";
public void test_me()
{
//Form1 fm = new Form1();
MessageBox.Show(Form1.deva);
}
Answer on the title question.
Read Jon Skeet's comment for explanation of reason why your approach not workiing.
If you want have access to the variables of another instance, then you need in someway have reference to that instance
One way pass it in the constructor of Other
public class Other: Form1
{
private readonly Form1 _Form1;
public Other(Form1 form1)
{
_Form1 = form1;
}
public void test_me()
{
MessageBox.Show(_Form1.deva);
}
}
Then where you create new instance of Other pass instance of your Form1 ti the constructor of Other
public class Form1
{
private void button9_Click(object sender, EventArgs e)
{
Other ks = new Other(this);
ks.test_me();
}
}
default value is set a every new instance
if you want to keep last value you make a static property
public static string deva = "123";

How can I take a parameter or call a function which is declared in other braces?

I'm beginner in C# and having great difficulty to figure our some issues. So I hope my terminology does not matter. Here is my question. Let's say I have the following code:
namespace WindowsFormsApplication8
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//code starts
//...
//if(...) {
//...
//string parameter = abc.ToString();
//}
//code ends
}//Form1 ends
private void button1_Click(object sender, EventArgs e)
{
//code here
}
private void button2_Click(object sender, EventArgs e)
{
textBox1.Text = parameter;
button1.Perform();
}
}
}
I have difficulties here.
How can I use the string declared in Form1 called parameter inside button2_Click?
textBox1.Text = parameter; doesn't work.
Use a member variable.
public partial class Form1 : Form
{
private string parameter = null;
public Form1()
{
InitializeComponent();
// ...
parameter = abc.ToString();
}

using a listbox to display items from a class

My program compiles and to me it makes sense.
I want to know how to get 'name' to list in my listbox.
I'm trying to use an array of classes so I can add salesmen. A new class will be created every time a person is to be added.
This way the name is a way of calling all the data in that class.
When I execute the program everything looks like its doing what it's suppose to do but it just lists 'form1' in the list box when i press the list names button
This is what i mean:
Where am I going wrong?
SalesmanClass
namespace WindowsFormsApplication1
{
class SalesmanClass
{
private string name;
public string cNum;
public string Email;
public string address;
public string gArea;
public int tSales;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Form 1
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Form2 w2;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (w2 == null)
{
w2 = new Form2();
w2.Show();
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
Object names;
names = Name;
listBox1.Items.Add(Name);
}
}
}
Form 2
//form2
namespace WindowsFormsApplication1
public partial class Form2 : Form
{
SalesmanClass[] salesman = new SalesmanClass[] { };
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text.Trim().Length != 0)
{
for (int i = 0; i > salesman.Length; i++)
{
if (salesman[i] == null)
{
salesman[i].Name = textBox1.Text;
break;
}
}
this.Close();
}
else
{
MessageBox.Show("Please Input a Name");
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
In this method:
private void button2_Click(object sender, EventArgs e)
{
Object names;
names = Name; // <--- Using this.Name, i.e. Form.Name, NOT SalesmanClass.Name
listBox1.Items.Add(Name);
}
You have accidentally used the Name property of the Form itself (which naturally is "form1").
You need to have a SalesmanClass object at this point, and use the Name property of that instead.
You don't currently have a list of salesmen in your Form1, so you will need to add one and use that.
Also, if you have a list or array of SalesmanClass objects, you should create a List<string> from them and use that to initialise the listbox, something like:
SalesmanClass[] salesmen = new SalesmanClass[] {};
// ...
List<string> names = new List<string>();
foreach (var salesman in salesmen)
names.Add(salesman.Name);
listBox1.Items.AddRange(names);
You can do this using Linq too, but I don't want to confuse you by introducing that into the mix!
In your button2_Click, you have :
names = Name;
What does this Name belong to ? I suspect it belongs to Form1, that's why it's been displaying "form1". If that's the case, you just need to get your SalesmanClass object and get the Name from it.

Categories

Resources