Using list between forms - c#

I generated a list on form1 who's contents are numbers and a letter in the form of K000-000. I then want to open form2. On form 2 I have a text box, a list box and a button. In the text box you will type some more number in like 12345. When you click the button I want it to add the contents of form1's list with a "-" on the end and the contents you typed in Form2's textbox. So the listbox will be K000-000-12345. I'm not sure how to properly use Form1's list on Form2 and also add to it.
Form1
DesignNo.FindByItem(electype, (int.Parse)(dwgno));
List<DesignNo> Electrode = DesignNo.FindByItem(electype, (int.Parse)(dwgno));
if (Electrode.Count <= 0)
{
MessageBox.Show("Unknown Electrode Number");
}
frmElectrode frmelec = new frmElectrode();
frmelec.Show();
frmelec being Form2 in the example.

1-Using Static property
public static List<int> list;
public Form1()
{
list=new List<int>();
InitializeComponent();
}
in Form2 access list like this
Form1.list.Add(item);
2-using constructor
public static List<int> list;
public Form1()
{
list=new List<int>();
InitializeComponent();
}
public void ShowForm2()
{
var form2=new Form2(List);
form2.show();
}
in Form2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public static List<int> _list;
public Form2(List<int> list)
{
_list=list;
InitializeComponent();
}
}

create a public property inside Form 2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public string Content { get; private set; }
public void ButtonOkOnClick()
{
this.Content = this.textBox1.Text;
this.Close();
}
}
Consume the public property in Form1 after Form2 gets closed
public Form1()
{
InitializeComponent();
Form2 form2 = new Form2();
form2.Show();
form2.Closed += (sender, args) => this.list.Add(form.Content);
}
This way the dependency is the right direction, form2 is just a input form and can be reused without any dependencies.

A clean way to share some state (in your case dictionary of keys) is via some shared service (singleton), so:
You could create a class (e.g. ElectrodeManager) which will hold a dictionary of electrodes (empty in the first place).
In the Form1 you will populate that dictionary via specified method on that class (e.g. AddElectrode(string electrodeType, string electrodeKey) -> which will add new item into the dictionary)
- so you will have Dictionary<string, string> that holds e.g. {"T1", "K000-000"}, {"T2", "K000-0001"} ...
In the Form2 you will work that dictionary from the ElectrodeManager and you will append string from the textbox onto electrode's key.
Example:
public class ElectrodeManager
{
#region Singleton Pattern
private static ElectrodeManager instance;
public static ElectrodeManager Instance
{
get
{
if (instance == null)
instance = new ElectrodeManager();
return instance;
}
}
private ElectrodeManager()
{
electrodes = new Dictionary<string, string>();
}
#endregion
#region Fields
private Dictionary<string, string> electrodes;
#endregion Fields
#region Methods
public void AddElectrode(string eType, string eKey)
{
if (!electrodes.ContainsKey(eType))
{
electrodes.Add(eType, eKey);
}
}
public void AppendStringToElectrodeKey(string eType, string keyAddendum)
{
string electrodeKey = String.Empty;
if (electrodes.TryGetValue(eType, out electrodeKey))
{
electrodes[eType] = String.Format("{0}-{1}", electrodes[eType], keyAddendum);
}
}
public IDictionary<string, string> GetElectrodes()
{
return electrodes;
}
#endregion Methods
}
Usage inside Form1 (somewhere in generation logic):
ElectrodeManager.Instance.AddElectrode("T1", "K000-000");
ElectrodeManager.Instance.AddElectrode("T2", "K000-001");
Inside Form2 (button click):
ElectrodeManager.Instance.AppendStringToElectrodeKey("T1", textBox.Text);
ElectrodeManager.Instance.AppendStringToElectrodeKey("T2", textBox.Text);
Of course, you could easily switch data type to the List<string> if that suits you better.

Related

Add ONLY checked items from a checklistbox to a listView control

My situation:
I have a populated checklistbox control on Form1.
Then I have a listView control on Form2.
I would like for the user to be able to check items on the checklistbox on Form1, then click on a button on Form1 to open Form2.
Form2 contains the listView control, that I want to populate with only the checked items from checklistbox on Form1.
I tried
namespace Boodschappenlijst
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static string[] strKruideniersw = new string[] { Boodschappenlijst.producten[0], Boodschappenlijst.producten[1], Boodschappenlijst.producten[2] };
public static string[] strVerswaren = new string[] { Boodschappenlijst.producten[3], Boodschappenlijst.producten[4], Boodschappenlijst.producten[5] };
public static string[] strVerzorgingspr = new string[] { Boodschappenlijst.producten[6], Boodschappenlijst.producten[7], Boodschappenlijst.producten[8], Boodschappenlijst.producten[9] };
public static List<string> kruidenierswList = new List<string>(strKruideniersw);
public static List<string> verswarenList = new List<string>(strVerswaren);
public static List<string> verzproductenList = new List<string>(strVerzorgingspr);
public static string[] strKruidenierswCh;
public void Form1_Load(object sender, EventArgs e)
{
clbKruidenierswaren.Items.AddRange(strKruideniersw);
clbVerswaren.Items.AddRange(strVerswaren);
clbVerzproducten.Items.AddRange(strVerzorgingspr);
strKruidenierswCh = clbKruidenierswaren.CheckedItems;
}
// TODO
// public string kruidenierswChecked = clbKruidenierswaren.CheckedItems;
private void button1_Click(object sender, EventArgs e)
{
// Create a new instance of the Form2 class
Form2 form2 = new Form2();
// Show the settings form
form2.Show();
}
}
public abstract class Boodschappenlijst : Form1
{
public static string[] producten = new string[] { "Peper", "Zout", "Kruidnagel", "Sla", "Komkommer", "Tomaten", "Tandpasta", "Shampoo", "Wax", "Deodorant" };
// Not working.. clbKruidenierswaren is not static.
List<string> items = clbKruidenierswaren.CheckedItems.Cast<string>().ToList();
// Make form1 controls accessible for other classes?
// Form1 form1 = Application.OpenForms.OfType<Form1>().FirstOrDefault();
}
}
but the I get the error
A field initializer cannot reference the non-static field, method, or property 'Form1.clbKruidenierswaren'.
Can you please direct me to a solution that works?
You should make a constructor in the class like this:
Class itself:
public class Boodschappenlijst
{
public static string[] producten { get; set; } = new string[] { "Peper", "Zout", "Kruidnagel", "Sla", "Komkommer", "Tomaten", "Tandpasta", "Shampoo", "Wax", "Deodorant" };
private List<string> Items { get; set; }
public Boodschappenlijst(List<string> items)// << Constructor
{
Items = items;
}
}
And then make an instance the class like so:
On the place (Form?) you have clbKruidenierswaren:
Boodschappenlijst boodschappenLijst =
new Boodschappenlijst(clbKruidenierswaren.CheckedItems.Cast<string>().ToList());
The problem is you're passing UI objects around, you should be passing data around instead. Here's an example of a Form that can be given data during construction.
public class BaseForm : Form
{
public object InitialisationData { get; set; }
}
public partial class MagicForm : BaseForm
{
public string MyBindableGuy;
public MagicForm()
{
InitializeComponent();
MyBindableGuy = InitialisationData as string;
}
}
and open it with:
var myForm = new MagicForm();
myForm.InitialisationData = "Hi, I'm a string.";
myForm.Show();
public partial class Form1 : Form
{
// Todo declare the variables
private List<string> kruidenierswList;
private List<string> verswarenList;
private List<string> verzproductenList;
public Form1()
{
InitializeComponent();
// call the instance once and add that to the variable lijst
Boodschappenlijst lijst = Boodschappenlijst.Instance; // <- # others on S/O this is just used as information I know I could do a new as well.
// initialize the variables
kruidenierswList = new List<string>() { lijst.Products[0], lijst.Products[1], lijst.Products[2] };
verswarenList = new List<string>() { lijst.Products[3], lijst.Products[4], lijst.Products[5] };
verzproductenList = new List<string>() { lijst.Products[6], lijst.Products[7], lijst.Products[8], lijst.Products[9] };
}
public void Form1_Load(object sender, EventArgs e)
{
// populate the checklist boxes
clbKruidenierswaren.Items.AddRange(kruidenierswList.ToArray());
clbVerswaren.Items.AddRange(verswarenList.ToArray());
clbVerzproducten.Items.AddRange(verzproductenList.ToArray());
}
private void button1_Click(object sender, EventArgs e)
{
// Create a new instance of the Form2 class
Form2 form2 = new Form2();
// Show the settings form
form2.Show();
}
}
public class Boodschappenlijst
{
private static Boodschappenlijst instance;
public string[] Products
{
get;
private set;
}
private Boodschappenlijst()
{
Products = new string[] { "Peper", "Zout", "Kruidnagel", "Sla", "Komkommer", "Tomaten", "Tandpasta", "Shampoo", "Wax", "Deodorant" };
}
public static Boodschappenlijst Instance
{
get
{
// singleton initialization => look for design pattern - singleton <- Design patterns can brighten your day.
//
return instance == null ? instance = new Boodschappenlijst() : instance;
}
}
}

Send text to texbox in another form without making new windows

I need to make windows forms program, that:
a) shows 2 forms with one textbox and one button each
b) when you press the button on one form, program copies text from that form to second form
c) when you press the button on the second form, program copies text from that form to first form
I've tried several different aproaches and got bogged down in encapsulation problems, since both forms has to be in separate instances, right? I've managed to make it work, so it creates new instance of form with new text in textbox every time you click, but after several steps I ended up with screen full of new windows and I need it to show only 2 windows through whole runtime.
Create the windows in your Main method, but don't show them immediately, then access them through the static properties:
public static class Program {
public static Form1 Form1 { get; private set; }
public static Form2 Form2 { get; private set; }
public static Int32 Main(String[] args) {
using( Program.Form1 = new Form1() )
using( Program.Form2 = new Form2() ) {
Application.Run( Program.Form1 ); // Form1's `Load` method would then show `Form2`
}
Program.Form1 = Program.Form2 = null;
return 0;
}
}
Form1 (is responsible for showing Form2 because Application.Run only shows a single form itself):
public class Form1 : Form {
protected override void OnLoad(...) {
Program.Form2.Show();
}
private void Button1_Click(...) {
Program.Form2.TextBox1.Text = this.textBox1.Text;
}
}
Form2 (you need to expose its TextBox via a public property):
public class Form2 : Form {
public TextBox TextBox1 { get { return this.textBox1; } }
}
Here's an example that shows how to pass a reference to the first form, into the second form using its Constructor. That reference is stored at class level so it can be used later. The exact same code/form is being used for both instances:
public partial class Form1 : Form
{
private Form1 target = null;
public Form1()
{
InitializeComponent();
this.Text = "Instance #1";
this.target = new Form1(this);
this.target.Text = "Instance #2";
this.target.Show();
}
public Form1(Form1 target)
{
InitializeComponent();
this.target = target;
}
private void button1_Click(object sender, EventArgs e)
{
if (this.target == null || this.target.IsDisposed)
{
this.target = new Form1(this);
this.target.Show();
}
this.target.textBox1.Text = this.textBox1.Text;
}
}
got bogged down in encapsulation problems, since both forms has to be in separate instances, right?
"encapsulation" immediately made me think of nested classes. The quintessential use case is for a class that is not/should not be used anywhere except in the containing class.
The idea is to allow clients to instantiate Form1 but have no access to Form2 or any of its members. If you need to expose anything from Form2 I suggest you write Form1 properties so that the client sees everything coming from Form1 only.
public class Form1 : Form {
protected Form Sibling { get; set; }
public Form1() {
Sibling = new Form2(this);
}
protected override void OnLoad(...) {
Sibling.Show();
}
private void Button1_Click(...) {
Sibling.TextBox1.Text = this.textBox1.Text;
}
protected class Form2 : Form {
protected Form Sibling { get; set; }
public Form1 ( Form mySibling ) {
Sibling = mySibling;
}
private void Button1_Click(...) {
Sibling.TextBox1.Text = this.textBox1.Text;
}
} // Form2
} // Form1

Cannot get selectedItem to textbox

I'm trying to get listbox selected item from one form 1 to display on textbox on form 2.
So far it's working partly.
The problem is that it only gets the selectedItem that was selected at the start of the application. If the user selects a new item, it still gets the one that was selected as default.
Form 1 MainForm:
public MainForm()
{
public string GetListBoxSelectedItem()
{
if (Animallst.SelectedItem != null) //Animallst is the listbox
{
return Animallst.SelectedItem.ToString();
return string.Empty;
}
}
private void foodbtn_Click(object sender, EventArgs e)
{
FoodRegister foodForm = new FoodRegister();
foodForm.Show();
}
}
Form 2 FoodRegister:
public partial class FoodRegister : Form
{
private RecipeManager m_foodmanager = new RecipeManager();
public FoodRegister()
{
InitializeComponent();
MainForm main = new MainForm();
Nametxt.Text = main.GetListBoxSelectedItem();
//My initializations
InitializeGUI();
}
}
These two lines are not at all doing what you want them to do. You're creating an entirely new instance of MainForm, which has nothing to do with the original instance. And so GetListBoxSelectedItem() doesn't do what you want either.
MainForm main = new MainForm();
Nametxt.Text = main.GetListBoxSelectedItem();
Instead, pass a reference to the original Form into the second Form:
public FoodRegister(MainForm main)
{
InitializeComponent();
Nametxt.Text = main.GetListBoxSelectedItem();
...
And then call it like this:
FoodRegister foodForm = new FoodRegister(this);
foodForm.Show();
A couple of things to mention:
The line return string.Empty is redundant. Because of the line above it, this line becomes unreachable
In your FoodRegister for, you create a new instance of your main form. This then wipes anything that the main form was holding - i.e. Animallst.SelectedItem.ToString();
An easy way to handle this is to set the value to a static variable - that way you won't have to create a new instance of the form to access it.
Main form:
public static string GetListBoxSelectedItem()
{
if (Animallst.SelectedItem != null) //Animallst is the listbox
{
return Animallst.SelectedItem.ToString();
}
else { return string.Empty(); }
}
Food Register:
public FoodRegister()
{
InitializeComponent();
MainForm.GetListBoxSelectedItem();
//My initializations
InitializeGUI();
}
Haven't played with WinForms in awhile but here goes
In Form 2
public partial class FoodRegister : Form
{
private RecipeManager m_foodmanager = new RecipeManager();
public FoodRegister()
{
InitializeComponent();
//My initializations
InitializeGUI();
}
public void SetText(string txt)
{
Nametxt.Text = txt;
}
}
In Form 1
public MainForm()
{
private readonly FoodRegister foodForm = new FoodRegister();
private void foodbtn_Click(object sender, EventArgs e)
{
foodForm.SetText(Animallst.SelectedItem == null ? "" : Animallst.SelectedItem.ToString());
foodForm.Show();
}
}
I replaced
GetListBoxSelectedItem()
with
Animallst.SelectedItem == null ? "" : Animallst.SelectedItem.ToString()

Can't access public textBox7 created in form1, while in form2

I have a textbox7 created in form1, but I want to access it in another form, form 2 so I changed its modifiers to public
When I get on form2 i want it to perform the following
Form1.textBox7.ReadOnly = true;
but I get the following error
Error 1 An object reference is required for the non-static field,
method, or property
'WindowsFormsApplication1.Form1.textBox7' C:\Users\Admin\Google
Drive\AdminhomeGD\ztese\zprograma\WindowsFormsApplication1\WindowsFormsApplication1\formOpConfig.cs 73 46 WindowsFormsApplication1
i have no idea what's wrong
Edit:
I'm trying to use the following, on form1 (named Form1):
public Boolean gammamanual
{
get { return textBox7.ReadOnly; }
set { textBox7.ReadOnly = value; }
}
while on form2 (named formOpConfig):
namespace WindowsFormsApplication1
{
public partial class formOpConfig : Form
{
public formOpConfig(Form1 opener)
{
// this is a constructor
this.Opener = opener;
}
private Form1 Opener { get; set; }
public formOpConfig() { // initialization and stuff }
private void buttonExit_Click (object sender, EventArgs e)
{
if (checkBox3.Checked == true) { this.textBox7.gammamanual = false; }
else { this.textBox7.gammamanual = true; }
this.Hide();
}
I want it so that when the checkbox3 is checked and the form2 exited, the textBox7 will be editable manualy.
Edit:2 the problem was that form2 was started from form1, also, i had 2 different constructors in form2 (formOpConfig). the solution was adapting the main constructor using
private Form1 Opener { get; set; }
public formOpConfig(Form1 opener)
{
this.Opener = opener;
InitializeComponent(); //Stuff
}
meanwhile i was able to start formOpConfig from the Form1 using
formOpConfig painelconfig = new formOpConfig(this);
painelconfig.ShowDialog();
You cannot access an instance variable via class name, that works only if it's static. So you need an instance of Form1 to access a property/field of it. You could for example pass it via constructor from Form1 to Form2(if Form1 instantiates Form2) or use a property/method.
But instead of exposing the complete control i would only provide what is necessary, that's called Encapsulation. You could expose a public property with a meaningful name that describes the purpose of textBox7(change also this name). Presuming it's purpose is to show a username the property could be UserName:
public partial class Form1 : Form
{
public string UserName
{
get{return TxtUserName.Text;}
set{ TxtUserName.Text = value;}
}
// ...
}
Since you want to get/set the ReadOnly property of the TextBox you could provide another property:
public bool UserNameEditable
{
get{ return !TxtUserName.ReadOnly; }
set{ TxtUserName.ReadOnly = !value; }
}
Now you are able to get/set it from another Form if you have an instance of Form1:
public partial class Form2 : Form
{
public Form2(Form1 opener)
{
// this is a constructor
this.Opener = opener;
}
private Form1 Opener { get; set; }
private void SomeMethod()
{
this.Opener.UserName = "Tim";
this.Opener.UserNameEditable = false;
}
// ...
}
You need to pass the Form1 instance to the constructor of Form2 when you instantiate it. Another approach is to make the property Opener public and use that which suffers the disadvantage that you cannot be sure that it was set.
Another approach is using LINQ and Application.OpenForms which is elegant but error-prone:
var form1 = Application.OpenForms.OfType<Form1>().FirstOrDefault();
form1.UserName = "Tim";
Side-note: Form1 and Form2 are also crying for more meaningful names.
In a form, the controls are created with a private access modifier (see the designer code).
private System.Windows.Forms.TextBox
Therefore, these controls are not accessible from another form. What you should do is create a public or internal property on your form.
public TextBox TextBox7 { get { return textBox7; } }
Once you created an instance of Form1 in (an instance of) Form2, you can access this property.
Form1 frm = new Form1();
frm.TextBox7.ReadOnly = true;
You need to create form1 instance and make a public property to set the control within form1.
public partial class Form2: Form
{
private Form1 objForm1;
public Form2(Form1 frm)
{
InitializeComponent();
//get other form
this.objForm1= frm;
//call here public property of form1 which set controls properties within form1
this.objForm1.SetReadOnly = true;
}
}
Form1
public partial class Form1 : Form
{
//setter Property
public bool SetReadOnly
{
set{ this.TextBox7.ReadOnly= value;}
get{ return this.TextBox7.ReadOnly;}
}
//Form1 Constructor
public Form1()
{
InitializeComponent();
}
//Form1 Load
private void Form1_Load(object sender, EventArgs e)
{
Form2 frm = new Form2(this);
frm.Show();
}
}

Get data from another form

I have a listview in my Mainform and I need to get the value in the textbox and label in the other form name Add_Order?
Add_Order add = new Add_Order();
ListViewItem item = new ListViewItem();
item.Text = add.textBox3.Text;
item.SubItems.Add(add.label6.Text);
item.SubItems.Add(add.textBox2.Text);
item.SubItems.Add(add.textBox1.Text);
item.SubItems.Add(add.textBox3.Text);
mainform.listView2.Items.Add(item);
I personally would not expose the controls in your Add_Order Form. Your calling Form should not be aware of the internals of the Add_Order Form, only its public Methods and Properties. I would make a Public Method and use that to retrieve the information you need. something like this:
Add_Order.cs
public partial class Add_Order : Form
{
public Add_Order()
{
InitializeComponent();
}
public List<string> GetData()
{
List<string> list = new List<string>();
list.Add(textBox3.Text);
list.Add(label6.Text);
list.Add(textBox2.Text);
list.Add(textBox1.Text);
return list;
}
}
MainForm
private void button1_Click(object sender, EventArgs e)
{
Add_Order add = new Add_Order();
add.ShowDialog();
ListViewItem item = new ListViewItem();
List<string> data = add.GetData();
item.Text = data[0];
item.SubItems.Add(data[1]);
item.SubItems.Add(data[2]);
item.SubItems.Add(data[3]);
item.SubItems.Add(data[0]);
listView2.Items.Add(item);
}
You can pass the data to other forms in different ways like creating public classes to maintain data common data between forms or you can pass data using form constructor like :
Add_Order frmAddOrder=new Add_Order(data1,data2);
frmAddOrder.show();
and in your Add_Order Constructor :
public Add_Order (string data1,string data2)
{
InitializeComponent();
//you can access data1 and data2 here ...
}
I write a simple one for you:
Set element Modifiers to true in Add_Order form :
and get it in main form:
public partial class main : Form
{
public main()
{
InitializeComponent();
Get_Frm2_Data();
}
private void Get_Frm2_Data()
{
Add_Order frm2 = new Add_Order();
List<string> info= new List<string>;
info.Add( frm2.textBox1.Text);
.
.
.
}
}
edit
or make an structure:
Add_Order.cs
public partial class Add_Order : Form
{
public Add_Order()
{
InitializeComponent();
}
public Info Get_Data()
{
return new Info() { _textBox3 = textBox3.Text,
_label6 = label6.Text,
_textBox2 = textBox2.Text,
_textBox1 = textBox1.Text,
};
}
}
struct Info
{
public string _textBox3;
public string _label6;
public string _textBox2;
public string _textBox1;
}
Mainform.cs
public partial class main : Form
{
public main()
{
InitializeComponent();
Get_Frm2_Data();
}
private void Get_Frm2_Data()
{
Add_Order frm2 = new Add_Order();
frm2.ShowDialog();
Info lst_data= frm2.Get_Data();
ListViewItem item = new ListViewItem();
item.Text = lst._textBox3;
item.SubItems.Add(lst._label6);
item.SubItems.Add(lst._textBox2);
item.SubItems.Add(lst._textBox1);
mainform.listView2.Items.Add(item);
}
}

Categories