Click here to Skip to main content
15,888,521 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have three forms:

MainForm - Contains a List collection instantiated inside and two buttons where QuestionForm and ListViewForm are instantiated.
C#
public static List<Items> listOfItems = new List<Items>();

public List<Items> ItemList
{
   get { return listOfItems; }
   set { listOfItems = value; }
}

private void displayListViewToolStripMenuItem_Click(object sender, EventArgs e)
{
    ListViewForm lvf = new ListViewForm();
    lvf.Show();
}

private void newQuestioFormButton_Click(object sender, EventArgs e)
{
    QuestionForm qf = new QuestionForm();
    qf.Show();
    
    //Adds new item created to listOfItems 
    qf.ObjectCreatedToList += ObjectCreatedToListCollectionHandler;
}

QuestionForm - Contains controls for the user to enter values, those values are stored inside a class member variable that is created as an object and is then added inside the List Collection in the MainForm

C#
public EventHandler ObjectCreatedToList;

//Class Property that assigns values to member variables
public Items Info
{
    get
      {
        //Instantiates new Team class, assigns member variables to control values and returns new Team object
      }
    set
      {
        //set control values to Team member variables
      }  
}

private void addItemToolStripButton_Click(object sender, EventArgs e)
{
    if(ObjectCreatedToList != null)
    {
        ObjectCreatedToList(this, new EventArgs());
    }
    //Some Validation here to prevent control values to reset

    //If all control values are entered, this will clear the controls
    Info = new Items();
}

ListViewForm - Contains a ListView where when items are being added into the List Collection in QuestionForm, it should also be added to the listview control

The problem I am having is when all three forms are opened, the listview control inside the ListViewForm should be updated as new objects are being created by the QuestionForm.

Since the two forms are being instantiated inside a different button in the MainForm, I can't seem to figure out how to add the items inside the listview control without it not hitting the method or giving me an error.

What I have tried:

I've tried something similar to this:

QuestionForm
C#
public EventHandler ItemAlsoAddedToListViewChange;

private void addItemToolStripButton_Click(object sender, EventArgs e)
{
    if(ObjectCreatedToList != null)
    {
        ObjectCreatedToList(this, new EventArgs());
    }
    if(ItemAlsoAddedToListViewChange != null)
    {
        ItemAlsoAddedToListViewChange(this, new EventArgs());
    }
    //Some Validation here to prevent control values to reset

    //If all control values are entered, this will clear the controls
    Info = new Items();
}

ListViewForm
C#
public void UpdateListViewHandler(object sender, EventArgs e)
{
    MainForm mf = sender as MainForm;
    forech(Items itm in mf.ItemList)
    {
         ListViewItem lvi = new ListViewItem();
         lvi.Text = itm.IconName;
         lvi.ImageIndex = itm.ItemIconIndex;
         lvi.Tag = itm;

         itemListViewControl.Items.Add(displayIcon);      
}

MainForm
C#
private void displayListViewToolStripMenuItem_Click(object sender, EventArgs e)
{
    ListViewForm lvf = new ListViewForm();
    QuestionForm qf = sender as QuestionForm();
    gf.ItemAlsoAddedToListViewChange += UpdateListViewHandler;
    lvf.Show();
}


But it gave me a ArgumentNullException.

Can someone help? And elaborate what I am doing wrong? Thanks.
Posted
Updated 9-Jun-17 3:23am

1 solution

OK. The major problem here is that you aren't keeping a reference to either form when you create them - so you only ever get to "find" the form again when you get an event and can access it via the sender parameter to the event handler.
Plus, there is the fun that because you use Show to display each form, you can easily get multiple versions of the same form open at once - so which one are you supposed to update? And from which version of the other form?

You are handling this the wrong way: your ListViewForm and QuestionForm should have no idea that the MainForm (or each other) actual exist, they should report back to the parent Mainform via events which then uses properties and methods on the children to update them.

So, assuming that you want to limit the children to one instance showing each:
1) Create a class level private ListViewForm and QuestionForm reference variable, and set them both to null.
2) When you are supposed to show an instance of the form, check the variable. If it's not null, the form is already visible, and you need do nothing (but you might set the focus to it). If it isn't, create a new instance, set the variable, and add a handler for the FormClosing event.
2) When the closing event occurs, set the variable to null.

Now add an event to the QuestionForm, which is handled in the MainForm that indicates that there is new data - add a property (or a method) to fetch the new data.
In the MainForm handler, fetch the new data, and pass it to the ListViewForm for it to update itself.

That probably sounds complicated, but it isn't, not really - it's very obvious once you get your head round it.
Have a look at this: Transferring information between two forms, Part 3: Child to Child[^] - it includes an example.
 
Share this answer
 
Comments
pyschedelisaurus 9-Jun-17 9:46am    
ListViewForm is only suppose to be instantiated once, but QuestionForm can be instantiated multiple times (because in the MainForm there is also a read only textbox that keeps count of how many QuestionForms are opened).

As for the ListViewForm, I used the code below inside where it's once instantiated to prevent the user from opening up more than one:

if (displayListViewToolStripMenuItem.Checked == true)
{
//Checking for form to prevent second instance
if ((tlv == null) || (tlv != null && tlv.IsDisposed))
{
tlv.Show();
}
if (!tlv.Visible)
{
tlv.Show();
}
else
{
tlv.BringToFront();
}
}
else
{
//If display option is pressed again, this will prevent it from unchecking
displayListViewToolStripMenuItem.Checked = true;
}
OriginalGriff 9-Jun-17 10:10am    
Then you pick up the relevant instance from the event handler sender parameter and fetch the data from that.
And you either don't need the class level QuestionForm variable, or you make it a collection to which you Add and Remove instances if you need to access them without the event for another reason.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900