在表单中从用户控件 A 传递数据到用户控件 B。

3
各位大师好,我在处理一个问题时遇到了困难:如何在表单中传递两个用户控件的值。 我有一个名为“用户控件 A”的用户控件,其中包含组合框和按钮,以及一个名为“用户控件 B”的数据网格视图控件。现在,我想显示在数据网格视图中的来自用户控件A生成的数据。请问,我该如何将数据从UCA传递到UCB?以下是我想要传递的数据:
所以,在用户控制A中,当我点击名为“Generate”的按钮时,它将用下面GetConvo()函数中生成的数据填充用户控制B中的数据网格视图。
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


一般情况下,这是通过UserControlA上的事件来实现的,而UserControlB则订阅该事件 - 就像这里这里或者这里所示。 - stuartd
与任何其他控件一样:您可以引发事件(使用自定义的EventArgs派生类)或使用数据绑定。或者两者都可以。您还可以使用中间类来处理特定对象之间的特定关系。 - Jimi
我看到很多建议使用事件来实现,但是我还没有尝试过使用事件,不知道该如何正确地做。我是个新手。 - James
userControlB.Data = userControlA.Data,其中UserControlB中的Data是一个公共属性,用于获取或设置DataGridView.DataSource,而UserControlA中的Data是一个公共属性,用于获取在点击后生成的数据。 - Reza Aghaei
要从外部访问UserControl的控件,您需要将它们公开,或者定义公共属性来访问它们,或者定义公共属性来公开它们的特定属性。 - Reza Aghaei
谢谢 @RezaAghaei。稍后会尝试。 - James
2个回答

4

UserControlA是否知道/应该知道UserControlB?

UserControlA中创建一个类型为UserControlB的属性,每当您想要向UserControlB传递数据时,请使用您在UserControlB属性中拥有的实例。

它们分别是什么?是的,也许BindingNavigatorBindingSource的示例更加清晰:

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

然后,在表单中拖放BindingNavigatorBindingSource实例之后,将BindingNavigatorBindingSource属性设置为bindingSource1

UserControlA不知道/不应该知道UserControlB吗?

使用事件。这是最自然的方式。每天你都在使用它,像TextChangedSelectedIndexChanged等等。现在是为您的用户控件创建一个事件的时候了。
实际上,您需要在UserControlA中引发事件,然后在表单中,当您放置了UserControlAUserControlB的实例后,处理UserControlA事件并设置UserControlB属性。
为了更清楚一点,再以BindingNavigatorBindingSource为例:
public class BindingNavigator
{
    public event EventHanlder MovingNext;
    public void MoveToNextRecord()
    {
        MovingNext?.Invoke(this, EventArgs.Empty);
    }
}

当您在窗体上放置一个BindingNavigator的实例和一个BindingSource的实例时,处理bindingNavigator1MovingNext事件,并设置bindingSource1的位置:

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

想要了解更多有关事件的知识吗?请查看以下文档:


1
示例中的事件处理程序是一个lambda事件处理程序。如果您喜欢设计师,只需通过设计师来处理bindingNavigator1MovingNext事件即可。 - Reza Aghaei
1
@james,有什么我可以帮你在应用解决方案方面的吗? - Reza Aghaei

1
你可以在用户控件中创建静态变量并将数据传递给该变量。
在用户控件A或B中创建一个变量。
public static string info = string.empty;

在打开用户控件之前,您必须将数据传递给变量。

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

更新

在UsercontrolA中创建用户控件的静态实例

public static internal UsercontrolA uc;

现在在你的构造函数中。
public UsercontrolA(){
InitializeComponent();
uc = this;
}

你现在需要一个函数来执行显示操作。
public void showData(){
// your display codes
messagebox.show(info);
}

在最后,当你点击按钮后,还需要调用显示函数。
UsercontrolA.info = "hello";
new UsercontrolA();
UsercontrolA.us.showData();

我没有测试这些代码,但它肯定可以工作。


1
我想做的是在用户控件A中单击按钮后立即在数据网格视图中显示数据。我不确定这是否有效。 - James
2
我强烈反对这种解决方案,你根本不需要静态成员。请阅读其他帖子。 - Reza Aghaei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接