3

To masters out there, I'm having problem with passing values 2 user controls within a form. I have usercontrol A which has combobox and a button and control B that has a datagridview. Now I want to display the data in User Control B which is in the datagridview. How can I pass the data from UCA to UCB? Here's the data I want to pass:

So in User Control A when I clicked the button named Generate, it will fill the datagridview in User Control B with the data generated in the GetConvo() below.

public DataTable GetConvo() {
    DataTable table = new DataTable();
    table.Columns.Add("ConvoUser", typeof(Object));
    table.Columns.Add("Message", typeof(Object));
    table.Columns.Add("Date", typeof(Object));

    var _data = from data in User.GetMatchConvo(comboBox3.SelectedValue.ToString())
                select new {
                    convoUser = data.actor_id,
                    convoMessage = data.message,
                    convoDate = data.creation_timestamp
                };
    foreach (var data in _data) {
        table.Rows.Add(data.convoUser, data.convoMessage, data.convoDate);
    }

    //dataGridView1.AllowUserToAddRows = false;
    //dataGridView1.AllowUserToDeleteRows = false;
    return table;
}

private UserInterface User = new UserData();

enter image description here

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
James
  • 271
  • 1
  • 3
  • 13
  • Generally this is done using an event on UserControlA which UserControlB subscribes to - like [here](https://stackoverflow.com/questions/44716233/passing-data-between-usercontrols-c-sharp), [here](https://stackoverflow.com/questions/31706759/winform-passing-data-between-user-controls), or [here](https://stackoverflow.com/questions/5363159/moving-data-between-two-user-controls-in-winform-application) – stuartd Feb 05 '20 at 17:49
  • The same way you do with any other Control: you raise events (using custom `EventArgs` derived classes) or use DataBindings. Or both. You can also use *intermediate* classes that handle specific relations between specific objects. – Jimi Feb 05 '20 at 18:03
  • I see many suggestion to do it using Events but I'm not yet tried using Events I don't know how to properly do it. Newbie here.. – James Feb 05 '20 at 18:20
  • `userControlB.Data = userControlA.Data` while `Data` in `UserControlB` is a public property which gets or sets `DataGridView.DataSource` and `Data` in `UserControlA` is a public property which gets the data generated after click. – Reza Aghaei Feb 05 '20 at 21:27
  • To access controls of a UserControl from outside, you need to make them public, or you need to define public properties to access to them or public properties to expose specific properties of them. – Reza Aghaei Feb 05 '20 at 21:29
  • Thank you @RezaAghaei. Gonna try that later. – James Feb 06 '20 at 02:41

2 Answers2

4

UserControlA knows/should know UserControlB?

Then create a property of type of UserControlB in UserControlA, then whenever you want to pass data to UserControlB, use the instance which you have in UserControlB property.

Which is which? Right, Maybe the BindingNavigator and BindingSource example is a bit clearer:

public class BindingNavigator
{
    Public BindingSource BindingSource { get; set; }
    public int Position
    {
        get {return BindingSource?.Position ?? -1};
        set {if(BindingSource!=null) BindingSource.Position = value;}
    }
}

Then when you dropped an instance of the BindingNavigator and an instance of the BindingSource on the form, set BindingSource property of the BindingNavigator to bindingSource1.

UserControlA doesn't/shouldn't know UserControlB?

Use events. It's the most natural way. Every day you are using it, like TextChanged, SelectedIndexChanged, and so on. Time to create one for your user control.

In fact you need to raise event in UserControlA, then on the form, when you dropped an instance of UserControlA and an instance of UserComtrolB, handle UserControlA event and set UserControlB property.

To make it a bit clearer, again with BindingNavigator and BindingSource:

public class BindingNavigator
{
    public event EventHanlder MovingNext;
    public void MoveToNextRecord()
    {
        MovingNext?.Invoke(this, EventArgs.Empty);
    }
}

Then when you dropped an instance of the BindingNavigator and an instance of the BindingSource on the form, handle MovingNext event of bindingNavigator1 and set position of the bindingSource1:

bindingNavigator1.MovingNext += (obj, args) => {
    bindingSource1.Position +=1;
};

Want to learn more about events? Take a look at the following documentations:

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • 1
    The event handler in the example is a lambda event handler. If you prefer designer, just handle `MovingNext` event of `bindingNavigator1` by help of designer. – Reza Aghaei Feb 05 '20 at 18:48
  • 1
    @james anything that I can help you in applying the solution? – Reza Aghaei Feb 13 '20 at 12:56
1

you can create a static variable in usercontrol and pass data to this variable

in UserControl A or B Create a variable

public static string info = string.empty;

and before you open usercontrol you must pass data to variable

UsercontrolA.info = "hello";
new UsercontrolA();

UPDATE

create a static instance of usercontrol in UsercontrolA

public static internal UsercontrolA uc;

now in you ctor

public UsercontrolA(){
InitializeComponent();
uc = this;
}

You now need a function to perform the display operation

public void showData(){
// your display codes
messagebox.show(info);
}

And at the end, after you click button, also call the display function.

UsercontrolA.info = "hello";
new UsercontrolA();
UsercontrolA.us.showData();

I didn't test the codes but it definitely should work

Katana
  • 752
  • 4
  • 23
  • 1
    What I wanted to do is to display data in the datagridview right after the button was clicked in user contorol A. I'm not sure if this will work. – James Feb 05 '20 at 18:29
  • 2
    I strongly advise against this solution, you don't need static members at all. Read the other post. – Reza Aghaei Feb 06 '20 at 07:29