Developer
Developer

Reputation: 8636

Winforms Creating Instances of 2 forms in another form

Hi all I am having three forms in my application, my form1 will show some data from the database and I will have add/edit buttons, corresponding to the option selected by user I will load Form2 and Form3. Now I would like to refresh the data on Form1 after user clicking on save on any of the forms Form2, Form3

Generally we write for one instance as follows

Form1 _Form1;
public Form2(Form1 frm)
{
     _Form1 = frm;
}

private void button1_Click(object sender, EventArgs e)
{
  _Form1.UpDateData();
}

But I need the same code to execute for different forms for suppose

Now in Form3 I need to implement the same scenario Instead of having the Form1 Caller in Form2 I need create instance for Form3 when this form was called is it possible

Form3 _Form3;
public Form2(Form3 frm)
{
     _Form3 = frm;
}

private void button1_Click(object sender, EventArgs e)
{
  _Form3.UpDateData();
}

I need to change the caller based on the form called

Upvotes: 1

Views: 384

Answers (6)

You could use an delegate in a base form class.

//Declare public delegate
public delegate void CustomFormEvent(object sender);

// Create a base class 
public partial  class BaseUpdateForm : Form
{
public event CustomFormEvent UpdateData; // Event declaration
protected void CustomFormEventHandler() 
{
    if (this.UpdateData != null)
        UpdateData(this);
}
}

Use the base class for as many forms as you would like, just register the event in the calling form or class (owner).

public partial class ChildForm1 : BaseUpdateForm 
{
public ChildForm1()
{
    InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
    CustomFormEventHandler(); 
}
}

In the owner form where you want to use the reaised event:

private void button1_Click(object sender, EventArgs e)
{
    // Form2 or Form3 in your example
    ChildForm1 child1 = new ChildForm1();
    child1.UpdateData += UpdateDataFormEvent;
    child1.Show(); 
}

void UpdateDataFormEvent(object sender)
{
    Form frm = sender as Form; // just cast it back to form
    MessageBox.Show(frm.Text);   
}

It is the custom event solution.

Regards.

Upvotes: 0

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236208

Use DialogResult of Form2 and Form3 to refresh items on Form1:

// on Form1
using(var form2 = new Form2(item))
{
   if (form2.ShowDialog() == DialogResult.OK)
   {
        // update items
   }
}

On Form2 set it's DialogResult property to DialogResult.OK, DialogResult.Cancel etc. according to user's action. E.g. when user deleted item, set result to DialogResult.OK:

// on Form2
private void btnDelete_Click(object sender, EventArgs e)
{
    // delete item from db
    DialogResult = DialogResult.OK;
}

UPDATE - if you want to keep both forms opened, then you can't show Form2 as dialog, and code above will not work for you. You need to declare event of Form2:

// on Form2
public event EventHandler<ItemDeletedEventArgs> ItemDeleted;

public Form2(List<Item> items)
{
   ...
}

private void btnDelete_Click(object sender, EventArgs e)
{
    // delete item from db
    OnItemDeleted(itemId)
}

protected void OnItemDeleted(int itemId)
{
   if (ItemDeleted == null)
       return;

   ItemDeleted(this, new ItemDeletedEventArgs(itemId));
}

Subscribe to this event on Form1:

private void form2_ItemDeleted(object sender, ItemDeletedEventArgs e)
{
    int itemId = e.ItemId;
    // update items
}

Where ItemDeletedEventArgs is a custom class inherited from EventArgs:

public class ItemDeletedEventArgs : EventArgs
{
    public ItemDeletedEventArgs(int itemId);
    {
        ItemId = itemId;
    }

    public int ItemId { get; private set; }
}

If you don't want to follow all these Microsoft guidlines of events of type EventHandler, arguments of type EventArgs, then you can use simple event of type Action<int>:

public event Action<int> ItemDeleted;

And raise it this way:

if (ItemDeleted != null)
    ItemDelted(itemId);

Upvotes: 1

Pedro
Pedro

Reputation: 388

Why not use a publisher\subscriber pattern. So that Form1 is subscribing to events from Form2 and Form3, or vice-versa. It's a more decoupled and flexible solution.

Upvotes: 0

Paul Murphy
Paul Murphy

Reputation: 675

It sounds like you need an interface

    public interface IUpdateData
    {
      void UpdateData();
    }

    //your forms will all implement the interface
    public class Form2 : Form, IUpdateData
    {
       public void UpdateData()
       {
          //some implementation
       }
    }

    public class Form3 : Form, IUpdateData
    {
       public void UpdateData()
       {
          //some implementation
       }
    }

Now back in your main form you accept instances of IUpdateData

    IUpdateData _form;
    public Form1(IUpdateData frm)
    {
         _form = frm;
    }

Now in the click event you simply call your update data method

    private void button1_Click(object sender, EventArgs e)
    {
      _form.UpdateData();
    }

Upvotes: 2

P&#233;ter
P&#233;ter

Reputation: 2181

Use interfaces.

public interface IUpdateData
{
  void UpdateData();
}

public class Form1 : Form, IUpdateData {...}
public class Form3 : Form, IUpdateData {...}

public class Form2 : Form
{
  private IUpdateData _parentForm;
  public Form2(IUpdateData _parentForm){...}
  private void btnDelete_Click(object sender, EventArgs e)
  {
    _parentForm.UpdateData();
  }
}

Or you can make a subsystem that allow to report data changes and allow to subscribe to recieve the changes.

Upvotes: 3

R&#233;mi
R&#233;mi

Reputation: 3967

you could do something like this

btnShowForm2.click(object sender, EventArgs e)
{
    Form2 frm = new Form2();
    DialogResult dr = frm.ShowDialog();
    if(dr != DialogResult.OK)
        return;

    //call a method to update your data here
    //this way you will reuse this with the other form
}

Upvotes: 0

Related Questions