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()
{
}
}
Related
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 :) ...
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.
I've created User Control in my WFA (Windows Form Application) and I want to pass value from my MainForm.cs to UserControl.cs but I have no idea on how to do that. Here are my values I want to pass to the UserControl.cs
public partial class MainForm : Form
{
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (ProcOpen)
{
//THESE
int vlInt = m.ReadByte("base+007C1DAC,0x14,0x4");
int roomID = m.ReadByte("base+003CA150,0x0");
double diffValue = m.ReadDouble("base+007B4A3C,0x0,0x2c,0x10,0x7ec,0x300");
}
}
}
To
public partial class FirstCustomControl : UserControl
{
public FirstCustomControl()
{
InitializeComponent();
}
private void FirstCustomControl_Load(object sender, EventArgs e)
{
//GET THE VALUES HERE
}
}
you can define a property for your UC then set the property from the parent;
public partial class FirstCustomControl : UserControl
{
public static dynamic vlInt;
public static dynamic roomID;
public static dynamic diff;
public FirstCustomControl()
{
InitializeComponent();
}
public void NotifyValueChanged(){
label1.text = vlInt.ToString();
label2.text = roomID.ToString();
label3.text = diff.ToString();
}
private void FirstCustomControl_Load(object sender, EventArgs e)
{
}
}
Then in your MainForm
public partial class MainForm : Form
{
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (ProcOpen)
{
//THESE
FirstCustomControl.vlCount = m.ReadByte("base+007C1DAC,0x14,0x4");
FirstCustomControl.roomID = m.ReadByte("base+003CA150,0x0");
FirstCustomControl.diff = m.ReadDouble("base+007B4A3C,0x0,0x2c,0x10,0x7ec,0x300");
firstCustomControl1.NotifyValueChanged();
}
}
}
I've got a Main Form (frm_Main) and Settings Form (frm_Settings) and I would like to update a control, which is in frm_Main, from frm_Settings. So far I've tried adding a method in frm_Main and then accessing that from frm_Settings in hopes for it to work but it did't. Here is the code for my current method:
Main Form
public partial class frm_Main : Form
{
public frm_Main()
{
}
public void ChangeBackColor(Color color)
{
richTextBox.BackColor = color;
}
}
Settings Form
public partial class frm_Settings : Form
{
public frm_Settings()
{
}
private void pbcl_editorBackColor_Click(object sender, EventArgs e)
{
ColorDialog editorBackColor = new ColorDialog();
if (editorBackColor.ShowDialog() == DialogResult.OK)
{
Variables.Editor_BackColor = "#" + editorBackColor.Color.ToArgb().ToString("X");
Color colour = ColorTranslator.FromHtml(Variables.Editor_ForeColor);
var Main = new frm_Main();
Main.ChangeBackColor(colour);
}
}
}
Upon click the 'OK' button on the ColorSelectorDialog, nothing happens, there is no update whatsoever. What am I doing wrong here?
Try this
Settings.cs
public partial class frm_Settings : Form
{
private frm_Main _main;
public frm_Settings(frm_Main main)
{
_main = main;
}
private void pbcl_editorBackColor_Click(object sender, EventArgs e)
{
ColorDialog editorBackColor = new ColorDialog();
if (editorBackColor.ShowDialog() == DialogResult.OK)
{
Variables.Editor_BackColor = "#" + editorBackColor.Color.ToArgb().ToString("X");
Color colour = ColorTranslator.FromHtml(Variables.Editor_ForeColor);
_main.ChangeBackColor(colour);
}
}
}
Main.cs
public partial class frm_Main : Form
{
public frm_Main()
{
}
private void LaunchSetting()
{
var settings = new frm_Settings(this);
settings.ShowDialog();
}
public void ChangeBackColor(Color color)
{
richTextBox.BackColor = color;
}
}
EDIT:
We can also handle it to create an event
Settings.cs
public partial class frm_Settings : Form
{
public delegate void ColorChangedHandler(Color color);
public event ColorChangedHandler OnColorChangedHandler;
public frm_Settings()
{
}
private void pbcl_editorBackColor_Click(object sender, EventArgs e)
{
ColorDialog editorBackColor = new ColorDialog();
if (editorBackColor.ShowDialog() == DialogResult.OK)
{
Variables.Editor_BackColor = "#" + editorBackColor.Color.ToArgb().ToString("X");
Color colour = ColorTranslator.FromHtml(Variables.Editor_ForeColor);
if (OnColorChangedHandler != null)
{
OnColorChangedHandler(colour);
}
}
}
}
Main.cs
public partial class frm_Main : Form
{
public frm_Main()
{
}
private void LaunchSetting()
{
var settings = new frm_Settings(this);
settings.OnColorChangedHandler += OnColorChanged;
settings.ShowDialog();
}
private void OnColorChanged(Color color)
{
ChangeBackColor(color);
}
public void ChangeBackColor(Color color)
{
richTextBox.BackColor = color;
}
}
I want to Use an instance of a class made in Form 1 in Form 2 (i changed it to a list for simplicity of example code:
Not only that, I want Form 2 to be able to modify it (Clear it at some point).
The advice I got was this, although I was not told how due to "no spoonfeeding allowed"
namespace automationControls.FileTime
{
public class Form_Main : Form
{
public List<string> folderList; //<---- i want to access this.....
private void button_showForm2_Click(object sender, EventArgs e)
{
Form_Log ConfirmBoxForm = new Form_Log(this);
ConfirmBoxForm.Show();
}
}
//form_Main opens form_Log
namespace automationControls.FileTime
{
public partial class Form_Log : Form
{
public Form_Log(Form_Main _f1)
{
InitializeComponent();
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
How.Do.I.AccessForm_Main.folderList.Clear();//<---- ............. in this function
}
}
}
Answered:In the constructor of Form_Log, store the reference to _f1 somewhere you can access it from elsewhere in Form_Log
Why don't you use the constructor that you have already added your form?
private Form_Main _mainForm;
public Form_Log(Form_Main _f1)
{
InitializeComponent();
_mainForm = _f1;
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
var myList = _mainForm.folderList;
}
Try This,
public class Form_Main : Form
{
public List<string> folderList; //<---- i want to access this.....
private void button_showForm2_Click(object sender, EventArgs e)
{
Form_Log ConfirmBoxForm = new Form_Log(this);
ConfirmBoxForm.Show();
}
}
Form log :
public partial class Form_Log : Form
{
private Form_Main _mainForm;
public Form_Log(Form_Main _f1)
{
InitializeComponent();
_mainForm = _f1;
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
_mainForm.folderList.Clear();
}
}
I don't know how advanced is your project but in this situation i would use delegates. Here is how i would do it:
public delegate void ModifyCollectionHandler(string parameter);
public delegate void ClearCollectionHandler();
public partial class Form1 : Form
{
public List<string> folderList;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 form = new Form2()
form.ClearItem+=form_ClearItem;
form.AddItem+=form_AddItem;
form.DeleteItem+=form_DeleteItem;
}
void form_DeleteItem(string parameter)
{
if (folderList == null)
return;
folderList.Remove(parameter);
}
void form_AddItem(string parameter)
{
if (folderList == null)
folderList = new List<string>();
folderList.Add(parameter);
}
void form_ClearItem()
{
if (folderList != null)
folderList.Clear();
}
}
public partial class Form2 : Form
{
public event ModifyCollectionHandler AddItem;
public event ModifyCollectionHandler DeleteItem;
public event ClearCollectionHandler ClearItem;
public Form2()
{
InitializeComponent();
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (ClearItem != null)
ClearItem();
}
}
I hope I helped you :)
Best regards
in the Form1 put this :
public static List<string> folderList;
you can simply call it from any form ex:Form2 like this :
From1.folderList.Clear();