1

I have the following static method that adds a selected product into an order.

    public static void addToOrderFromPicture(string product, string qty, string _price)
    {
        //I've cut the code as it's not important to the question.
        order.Add(product);

    }

The products are displayed as Controls on a flow layout panel. The user will click the 'Add to Order' button on the control. This activates the following method.

 private void btn_add_Click(object sender, EventArgs e)
 {
       if (Main.sessionInProgress == true)
       {
                OrderQty qty = new OrderQty(lbl_caseSize.Text.ToString(), lbl_wholesale.Text.ToString(), lbl_product.Text, lbl_volume.Text.ToString(), lbl_physical.Text, lbl_available.Text, lbl_oo.Text, lbl_inner.Text, lbl_pltQty.Text, lbl_repeat.Text);
                qty.StartPosition = FormStartPosition.CenterParent;
                DialogResult result = qty.ShowDialog();
                if (result == DialogResult.Yes)
                {
                    if (Main.roundCheck == true)
                    {
                        // MessageBox.Show(qty.qtyReturn.ToString());
                        qty.qtyReturn = autoRoundToCaseSize(qty.qtyReturn);
                        //MessageBox.Show(qty.qtyReturn.ToString());
                        Main.addToOrderFromPicture(lbl_product.Text.ToString(), qty.qtyReturn.ToString(), qty.priceReturn.ToString());
                    }
                    else
                    {
                        Main.addToOrderFromPicture(lbl_product.Text.ToString(), qty.qtyReturn.ToString(), qty.priceReturn.ToString());
                    }
                    btn_add.Text = "X";
                    btn_add.BackColor = Color.FromArgb(236, 112, 99);
                }
            } 
  }

The reason for the main function being static is so I can call it from this method. In Swift I would use a delegate to pass data between forms etc. However, I'm unsure on how to do this within C#.

Is there a similar method for passing data between forms as there is in Swift. How would I go about doing it? Or is there a way for me to call the method in Main without the need for it to be static.

EDIT: I don't think I've explained the forms etc very well so will try clear it up.

The addToOrderFromPicture method is contained within Main. This function adds products to the order list which is also static and contained within Main.

The 'btn_add_Click' method is contained in Product.cs which is a UserControl. This user control is displayed on a flowPanel which sits on the main form.

So the user clicks activates a function on Product.cs, this creates an instance of OrderQty.cs which is returns a qty to Product.cs - From Product.cs the addToOrder method within Main is called and the data like qty etc is passed to it.

So Product.cs -> OrderQty.cs -> Product.cs -> Main.cs

benjiiiii
  • 478
  • 10
  • 33
  • you may call any public method of your `Main` form if you have a reference to it – vasily.sib Nov 27 '18 at 09:10
  • 1
    Have a look at Event handling : https://stackoverflow.com/questions/7880850/how-do-i-make-an-event-in-the-usercontrol-and-have-it-handled-in-the-main-form - particularly the answer with 11 votes (at time of writing) near the end. You can declare the delegate to have whatever parameters you like – PaulF Nov 27 '18 at 09:58
  • @PaulF Hi, I'm looking at that and I think it's what I need. However, the 'ValueChangedEventArgs' is undefinred. Do you know if there's a certain reference required for it? – benjiiiii Nov 27 '18 at 13:05
  • You do not need the 'ValueChangedEventsArgs' parameter. First define a delegate in your class which matches the required method signature : _" public delegate void MyDelegate(string product, string qty, string _price);"_ . Then created a field _"public MyDelegate myDelegate;"_. In your Main class you then attach the method _"myUserControl.myDelegate += addToOrderFromPicture"_. In your click event, invoke the delegate with _"myDelegate?.Invoke(lbl_product.Text.ToString(), qty.qtyReturn.ToString(), qty.priceReturn.ToString());"_ – PaulF Nov 27 '18 at 13:32
  • Ahh my apologies I understand a little better now. I will try get this working – benjiiiii Nov 27 '18 at 13:33
  • 1
    Using this technique - multiple forms could all subscribe to the same event using the += operator & all of them will be invoked with the single call to myMethod.Invoke(). If you ever want to stop receiving the events in your main form, use the -= operator to remove the event. – PaulF Nov 27 '18 at 13:41

3 Answers3

1

Your form is still accessible after you've called this.Close() and ShowDialog has returned, so you can do this:

            OrderQty qty = new OrderQty(lbl_caseSize.Text.ToString(), lbl_wholesale.Text.ToString(), lbl_product.Text, lbl_volume.Text.ToString(), lbl_physical.Text, lbl_available.Text, lbl_oo.Text, lbl_inner.Text, lbl_pltQty.Text, lbl_repeat.Text);
            qty.StartPosition = FormStartPosition.CenterParent;
            DialogResult result = qty.ShowDialog();
            if (result == DialogResult.Yes)
            {
                qty.addToOrderFromPicture(lbl_product.Text.ToString(), qty.qtyReturn.ToString(), qty.priceReturn.ToString());
            }
Robin Bennett
  • 3,192
  • 1
  • 8
  • 18
  • Sorry I should be more clear. AddToOrderFromPicture is contained within my Main.cs. qty is an instance of OrderQty.cs. They're difference forms. – benjiiiii Nov 27 '18 at 09:23
  • OK, so which form is 'btn_add_Click' in? Can you just do 'this.addToOrderFromPicture' ? – Robin Bennett Nov 27 '18 at 09:24
  • 'btn_add_Click' is in Product.cs which is a UserControl held on a FlowPanel – benjiiiii Nov 27 '18 at 09:26
  • Is Main the parent form that created the other forms? If so, you could either pass on a reference to it, or do 'this.Parent.addToOrderFromPicture' – Robin Bennett Nov 27 '18 at 09:36
  • Hi, I've added to my question to try give a better understanding as I don't think I was very clear to begin with. – benjiiiii Nov 27 '18 at 09:44
1

Maybe you can keep your logic in a separate class instead of Main.

public class Service
    {
        public List<Product> Order { get; set; }

        public void addToOrderFromPicture(string product, string qty, string _price)
        {
            Order.Add(product);
        }
    }
Andrea
  • 247
  • 2
  • 4
  • 14
  • This is an interesting idea. I'll try some testing on it and see if it's viable. – benjiiiii Nov 27 '18 at 10:06
  • This still leads to the same issue of having to make the methods static in order for all the forms to be looking at the same instance of Service... Would I be able to get round that by passing the instance of service between the forms? – benjiiiii Nov 27 '18 at 10:17
  • I assume you are opening one form from another form (by a button click for example), can you pass the instance as a parameter when calling the new form in the constructor. – Andrea Nov 27 '18 at 10:26
  • Ahh that makes sense, so I create an instance of Service in Main for example, and the pass this between every form. – benjiiiii Nov 27 '18 at 10:43
  • Or you could make the business service 'static' – Robin Bennett Nov 27 '18 at 10:44
1

3 methods to do this.
First as the main window is created once use singleton pattern on it, declare a public static instance of form and access public methods,
Second pass a reference of main window to usercontrol and use its public methods.
Third add an event to usercontrol and hook handler in main window, whenever user clicks button, fire an event.

hessam hedieh
  • 780
  • 5
  • 18