当您需要两个用户控件(winforms)进行通信时的最佳实践

扩展问题

除了下面指定的原始问题之外,我还想添加一个新问题。 应用程序中的一个用户控件包含我需要从另一个用户控件访问的对象列表。 如何才能做到这一点? (我不相信控制的划分很好,但我宁愿不改变它……)

我应该通过事件和原始问题一起做,还是应该抓住父窗体,并使用它来查找控件的实例,并将其作为属性公开?


原来的问题

我有一个表单中的两个用户控件,我希望能够相互通信。 Usercontrol A应该能够在B上启动操作。

解决这个问题的首选方法是什么? 表单应该从A等待事件,然后在B上开始操作吗? 这有什么设计模式吗? 或者它是一个更简单的解决方案?

提前致谢! 🙂

两个用户控件不应该彼此了解。 如果您希望始终将它们作为一对处理,请考虑创建第三个用户控件来容纳它们。

表单应该从A等待事件,然后在B上开始操作吗?

是的,这是解决这个问题的唯一好方法。

扩展(奖金?)问题有点棘手。 我会通过让表单将用户控件委托给另一个用户控件上的方法来检索数据来处理这个问题。 然后,用户控件可以调用委托方法在另一个控件上调用该方法,而无需了解其实现。

  1. 将数据公开为属性。
  2. 在另一个用户控件上创建一个属性,父窗体将填充带有数据的控件的引用。

伪代码:

public UserControlA uca { get; set; } ... var items = uca.Items; 

我会这样做(我使用vb.net)

 Class MyUserControlA 'Inherits UserControl '(This line will be in your desinger file) Delegate Sub SomethingEventHandler (sender as object, e as EventArgs) '(assumes you are not going to override event args) Public Event SomethingEvent as SomethingEventHandler private _someData as String Public Readonly Property MyDataGrid as DataGridView Get Return DataGridView1 ' this is in the designer form of the user control End Get Public Property SomeData as string Get return _someData End Get Set(value as string) _someData as string End Set End Property Protected Sub OnSomethingEvent() RaiseEvent SomethingEvent(Me, EventArgs()) End Sub '....something happens and you want to raise the event OnSomethingEvent End Class 

实现主要表格如下

 Class MainForm Implements Form 'designer file '....other code Sub MyUserControlA1_SomethingEvent Handles MyUserControlA1.SomethingEvent 'instead of calling a property you could override eventArgs and return the control that way. MyUserControlB1.OtherDataGridView=MyUserControlA1.MyDataGrid End Sub End Class 

UserControlB如下:

 Class UserControlB Inherits UserControl ' designer form '...other code private _dataGrid as DataGridView=Nothing Public Property DataGrid() As DataGridView Get Return _dataGrid End Get Set(ByVal value As DataGridView) 'only set if null if _dataGrid is Nothing then _dataGrid = value End Set End Property 'do stuff with the control...I would always check for null function DoSomethingWithDataGrid as integer if _dataGrid IsNot Nothing then return _dataGrid.Items.Count End If End Sub End Class 

此代码未经过测试。

这种方式相当松散。 我想在理想的世界中,你可以在方法和属性中包装UserControlA DataGrid中所需的内容,并以这种方式使用它们。 但是如果有很多成员在DataGrid中进行引用,那么这肯定更容易。

我并不认为这是一个完美的设计。 我还在学习winforms架构。 你有什么专家的想法?

赛斯B斯皮尔曼