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()
Related
Hi I want to move listbox items to datagridview but I'm getting error can you see where I'm going wrong?
I got 2 form,1 datagridview,2 button ,1 listbox and 1 class ( For moving )
form1, got 2 items ( datagridview and 1 button( to open form 2 ))
form2, got 2 item ( listbox and 1 button( to move items datagridview rows )) I think I've created in your mind what I want to do so far, let me add pictures about application too
Picture 1 ( Form1 )
Picture 2 ( Form2 )
In class I added the functions for the buttons ( Shows in picture2 ( Button Load (Is ok) |Button Clear (Is ok) |Button Import (where I'm getting error))
well I have one solution for Import button (Below are the form 1 codes you can check)
public static Form1 instance;
public DataGridView dgv1;
public Form1()
{
InitializeComponent();
instance = this;
dgv1 = dataGridView1;
}
Below are the codes of form2 for the solution
private void btnImport_Click_1(object sender, EventArgs e)
{
foreach (var item in listBox1.Items)
{
int Import = Form1.instance.dgv1.Rows.Add();
Form1.instance.dgv1.Rows[Import].Cells["Email"].Value = item;
this.Close();
}
}
These codes solve my current problem, but it's very confusing when I want to do it for more than one object, so I want to call my operations by creating a method in class, but I get an error doing so
let me share codes for class
using System.Windows.Forms;
namespace Sndr01
{
internal class Class1
{
public string import (ListBox lst , DataGridView dgv)
{
childListForm frm = new childListForm();
string done = lst.ToString();
foreach (var item in lst.Items)
{
int imp = dgv.Rows.Add();
dgv.Rows[imp].Cells["Email Address"].Value = item.ToString();
frm.Close();
}
return done;
}
here is the my form1 codes
public partial class ListForm : Form
{
public DataGridView dgvv;
public ListForm()
{
InitializeComponent();
DataGridViewSettings(dgv1);
dgv1.DataSource = dgvv;
}
}
here is the my form2 codes
public partial class childListForm : Form
{
ListForm lf = new ListForm();
DataGridView dgvx;
public childListForm()
{
InitializeComponent();
dgvx.DataSource = lf.dgvv.DataSource;
}
private void kryptonbtnImport_Click(object sender, EventArgs e)
{
Class1 c1 = new Class1();
c1.import(lstLeadsbox,dgvx);
}
}
where I'm doing wrong? I'm so confused I would be very grateful if you could help
I may have told you a little too much and bored you, but I wanted to specify the details and not leave any question marks in your mind
Thanks
Rather than passing controls between forms a better way is to have an event to pass data from child to parent form.
In this generic example the ListBox is populated with month names. An event is used to pass data to the parent form where the parent form subscribes to the child form event.
Child form code
public partial class ChildForm : Form
{
public delegate void OnPassMonths(string text);
public event OnPassMonths PassMonths;
public ChildForm()
{
InitializeComponent();
listBox1.DataSource = System.Globalization
.DateTimeFormatInfo.CurrentInfo
.MonthNames.Take(12)
.ToList();
}
private void PassDataButton_Click(object sender, EventArgs e)
{
foreach (var monthName in (List<string>)listBox1.DataSource)
{
PassMonths?.Invoke(monthName);
}
}
}
In the main form, month names are added only if non-existing using the following extension method to keep code in the form clean and easy to read.
public static class DataGridViewExtensions
{
// in this case the cell is assumed to be 0, change if not 0
public static bool MonthNotExists(this DataGridView dgv, string month) =>
dgv.Rows.Cast<DataGridViewRow>()
.FirstOrDefault(row => row.Cells[0].Value.ToString()
.Equals(month)) == null;
}
Main form code
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void ShowChildForm_Click(object sender, EventArgs e)
{
ChildForm childForm = new ChildForm();
childForm.PassMonths += OnPassMonths;
try
{
childForm.ShowDialog();
}
finally
{
childForm.Dispose();
}
}
private void OnPassMonths(string month)
{
if (dataGridView1.MonthNotExists(month))
{
dataGridView1.Rows.Add(month);
}
}
}
I have a method, where I call a new Windows Form in Class A. And in the new Form, I use a Dropdown menu and store the selected Item from the Dropdown in a variable, called selectedItem.Now I have to access this selectedItem in Class A. I use the following code.
public class A
{
public method callingmethod()
{
ExceptionForm expform = new ExceptionForm();
expform.Show();
string newexp = expobj.selectedexception;
}
}
And my code in New Form,
public partial class ExceptionForm : Form
{
public string selectedexception = string.Empty;
private void btnExpSubmit_Click(object sender, EventArgs e)
{
selectedexception = this.comboBox1.GetItemText(this.comboBox1.SelectedItem);
this.Close();
return;
}
}
Now After clicking on Submit button, I get the correct value in selectedItem, But I could not pass it to Class A. How to retun to Class A?
If you are ok with posting ExceptionForm over parent form by disabling it, go for ShowDialog. But, if you do not wish to disable parent for and continue popping ExceptionForm as a new and independent window, try eventing back to parent form. Here I show an example on how to do so:
public partial class ExceptionForm : Form
{
public delegate void SelectValueDelegate(string option);
public event SelectValueDelegate ValueSelected;
private void btnExpSubmit_Click(object sender, EventArgs e)
{
this.Close();
if (this.ValueSelected!= null)
{
this.ValueSelected(this.comboBox1.GetItemText(this.comboBox1.SelectedItem));
}
return;
}
}
And in calling class:
public class A
{
public method callingmethod()
{
ExceptionForm expform = new ExceptionForm();
expform.ValueSelected += ExceptionForm_ValueSelected;
expform.Show();
}
private void ExceptionForm_ValueSelected(string option)
{
string newexp = option;
// Do whatever you wanted to do next!
}
}
Use ShowDialog() method.
expform.ShowDialog();
string newexp = expobj.selectedexception;
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
I have these objects in my project:
SchedulerList
SchedulerListItem
SchedulerListItemDetails
each one is a win forms control, which are used in forms of my application. The SchedulerList holds SchedulerListItems and each item can have SchedulerListItemDetails.
my code goes as follows:
//creating my initial list form
FrmListTesting f = new FrmListTesting();
f.Show();
The form has only one button that has a hard-coded parameter for testing purposes, as well as a SchedulerList control taht will hold the list items.
When the button is clicked the form does the following:
private void button1_Click(object sender, EventArgs e)
{
var control = this.Controls[1] as SchedulerList;
var path = #"D:\Share\Countries.txt";
var sli = new SchedulerListItem(path);
control.AddItem(sli);
}
my SchedulerListItem constuctor goes as follows:
public SchedulerListItem(string path)
{
InitializeComponent();
this.Name = Path.GetFileNameWithoutExtension(path);
this.SourcePath = path;
this.DestinationPath = GetDestinationPath(path);
}
And the AddItem method is defined as:
public void AddItem(SchedulerListItem item)
{
this.flPanel.Controls.Add(item);
}
The add item method works as intended, displays all the data that was required and displays it in the UI. The list item has a button that brings up the details form as such:
//the form constructor
public FrmSchedulerItemDetails(SchedulerListItem item)
{
InitializeComponent();
this.detailsControl = new SchedulerListItemDetails(item, this);
}
//control constructor
public SchedulerListItemDetails(SchedulerListItem item, Form owner)
{
InitializeComponent();
this.SourcePath = item.SourcePath;
this.DestinationPath = item.DestinationPath;
this.OldFormat = item.OldFormat;
this.ExportToExcel = item.ExportToExcel;
this.owner = owner;
this.underlyingItem = item;
}
And now the problem. After the SchedulerListItemDetails constructor is called and the data "gets initialized", when i look at the data inside the object its set to default values. it seams that everything that I set after InitializeComponent(); gets ignored.
things that i have tried:
hard-coding the values to see if primitives get passed correctly
settings breakpoints on every InitializeComponent() method to see the stack trace associated with setting to default values
none of the methods show any results... I know that if i use a form directly instead of using a control within a from i can set the values the way i want to, but I'm very confused as to why this other method with controls doesn't work.
EDIT 1:
the code for SchedulerListItemDetails:
public partial class SchedulerListItemDetails : UserControl
{
public SchedulerListItemDetails(SchedulerListItem item, Form owner)
{
InitializeComponent();
this.SourcePath = item.SourcePath;
this.DestinationPath = item.DestinationPath;
this.OldFormat = item.OldFormat;
this.ExportToExcel = item.ExportToExcel;
this.owner = owner;
this.underlyingItem = item;
}
public SchedulerListItemDetails()
{
InitializeComponent();
}
private Form owner = null;
private SchedulerListItem underlyingItem;
public Boolean ExportToExcel
{
get
{
return this.cbxExcel.Checked;
}
set
{
this.cbxExcel.Checked = value;
}
}
public Boolean OldFormat
{
get
{
return this.cbxOldFormat.Checked;
}
set
{
this.cbxOldFormat.Checked = value;
}
}
public String DestinationPath
{
get
{
return this.tbxDestinationPath.Text;
}
set
{
this.tbxDestinationPath.Text = value;
}
}
public String SourcePath
{
get
{
return this.tbxSourcePath.Text;
}
set
{
this.tbxSourcePath.Text = value;
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.owner.Close();
}
private void btnSave_Click(object sender, EventArgs e)
{
underlyingItem.SourcePath = this.SourcePath;
underlyingItem.DestinationPath = this.DestinationPath;
underlyingItem.OldFormat = this.OldFormat;
underlyingItem.ExportToExcel = this.ExportToExcel;
btnCancel_Click(sender, e);
}
}
I'll make an answer, because it should help you to solve your problem.
You have default (parameterless) constructor, which may be called and if it is called, then your constructor with parameters is not called.
Proper design would be something like
public partial class SchedulerListItemDetails : UserControl
{
public SchedulerListItemDetails()
{
InitializeComponent();
}
public SchedulerListItemDetails(SchedulerListItem item, Form owner): this()
{
this.SourcePath = item.SourcePath;
...
}
}
Notice this(), this ensure what parameterless constructor is called before (and InitializeComponent() as well, no need to duplicate it in another constructor).
Back to your problem. In your case it's like this
public partial class SchedulerListItemDetails : UserControl
{
public SchedulerListItemDetails()
{
InitializeComponent();
}
public SchedulerListItemDetails(SchedulerListItem item, Form owner)
{
InitializeComponent();
this.SourcePath = item.SourcePath;
...
}
}
Only one constructor can be called. So if you put breakpoint in parameterless one and it's triggered, then you have problems. Because you create somewhere SchedulerListItemDetails without setting it's properties (they stay default).
More likely problem is that you create new instance of that object (either before or after constructing proper, if your code ever construct such object) and that instance is what you inspect later.
So after i got a quick course of how win forms work i figured out what the problem was.
my code that i thought was enough is:
public FrmSchedulerItemDetails(SchedulerListItem item)
{
InitializeComponent();
this.DetailsControl = new SchedulerListItemDetails(item, this);
}
public SchedulerListItemDetails DetailsControl
{
get
{
return this.detailsControl;
}
set
{
this.detailsControl = value;
}
}
the this.detailsControl is the control im trying to setup, but as i have learned the correct way of replacing a component for a new one is:
public FrmSchedulerItemDetails(SchedulerListItem item)
{
InitializeComponent();
this.DetailsControl = new SchedulerListItemDetails(item, this);
}
public SchedulerListItemDetails DetailsControl
{
get
{
return this.detailsControl;
}
set
{
this.Controls.Remove(this.detailsControl);
this.detailsControl = value;
this.Controls.Add(this.detailsControl);
}
}
Feel kinda silly now :).
I have a parent form and a dialog. I need to pass info from the parent to the dialog
Here's what I have:
private void Item_Click(object sender, EventArgs e)
{
DialogResult result = DialogResult.OK;
DlgGraphOptions _frmDlgGraphOptions = new DlgGraphOptions();
_frmDlgGraphOptions.m_SerOpts = theDGroup.m_SerOpts;
_frmDlgGraphOptions.ShowDialog(this);
if (result == DialogResult.OK)
{
// Save the revised options to the Data Group
theDGroup.m_SerOpts = _frmDlgGraphOptions.m_SerOpts;
}
In DlgGraphOptions(child/dialog) form, I have intialitzed
public partial class DlgGraphOptions : Form
{
public GraphOpts_t m_SerOpts = new GraphOpts_t();
}
private void InitSettings(int idxSeries)
{
m_nMaxPts = m_SerOpts.GetMaxPts(idxSeries);
}
So I need to pass theDGroup.m_SerOpts from parent to the dialog,so I have done
_frmDlgGraphOptions.m_SerOpts = theDGroup.m_SerOpts;
in the parent. Now in the child:
public GraphOpts_t m_SerOpts = new GraphOpts_t;
This seems to be wrong. I don't want to be reinitializing it.
I think you should change your code in this way:
First, in the DlgGraphOptions form, change the constructor of DlgGraphOptions
// Force the caller to pass a GraphOpts_t
// Check if it is a valid instance or create one as new
public partial class DlgGraphOptions(GraphOpts_t input ) : Form
{
m_SerOpts = (input == null ? new GraphOpts_t() : input);
}
then create a public property with only the getter returning the internal GraphOpts
public GraphOpts_t Options
{
get{ return m_SerOpts; }
}
then, in the calling form, change uour code
// Pass the m_setOpts from theDGroup
DlgGraphOptions _frmDlgGraphOptions = new DlgGraphOptions(theDGroup.m_SerOpts);
if(DialogResult.OK == _frmDlgGraphOptions.ShowDialog(this))
{
// Save the revised (or new) options to theDGroup
theDGroup.m_SerOpts = _frmDlgGraphOptions.Options;
}
This approach will force the user of your dialog to pass an initialization value or null.
However your InitSettings will work with a initialized value and you don't have initialized two times your options instance.
(Actually there isn't a big improvement from your code, but I think it is a better approach)
Your child class should probably have the m_SerOpts as a property:
public partial class DlgGraphOptions : Form
{
public GraphOpts_t m_SerOpts { get; set; }
}
Your click event can probably be cleaned up like this:
private void Item_Click(object sender, EventArgs e)
{
using (DlgGraphOptions _frmDlgGraphOptions = new DlgGraphOptions()) {
_frmDlgGraphOptions.m_SerOpts = theDGroup.m_SerOpts;
if (_frmDlgGraphOptions.ShowDialog(this) == DialogResult.OK)
{
// Save the revised options to the Data Group
theDGroup.m_SerOpts = _frmDlgGraphOptions.m_SerOpts;
}
}
}
where in your DlgGraphOptions form, you need to set the form's DialogResult property in the OK or Save button event.
You could also just pass m_SerOpts object through the constructor:
public partial class DlgGraphOptions : Form
{
public GraphOpts_t m_SerOpts { get; }
public DlgGraphOptions(GraphOpts_t serOpts) {
InitializeComponents();
m_SerOpts = serOpts;
}
}