【问题标题】:Best practice when you need two user controls (winforms) to communicate需要两个用户控件(winforms)进行通信时的最佳实践
【发布时间】:2009-06-30 10:43:47
【问题描述】:

扩展问题

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

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


原来的问题

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

解决此问题的首选方法是什么?表单是否应该等待来自 A 的事件,然后在 B 上开始操作?有什么设计模式吗?还是更简单的解决方案?

提前致谢! :)

【问题讨论】:

    标签: c# winforms design-patterns user-controls


    【解决方案1】:

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

    表单是否应该等待来自 A 的事件,然后在 B 上开始操作?

    是的,这是处理此问题的唯一好方法。

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

    【讨论】:

    • 我尝试了委托方法,效果很好。 (你当然会说!)与其他人相比也相当优雅;)
    【解决方案2】:
    1. 将数据作为属性公开。
    2. 在另一个用户控件上创建一个属性,父窗体将使用对包含数据的控件的引用来填充该属性。

    伪代码:

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

    【讨论】:

      【解决方案3】:

      我会这样做(我使用 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架构。各位专家怎么看?

      赛斯·斯皮尔曼

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-15
        • 2017-03-18
        • 2013-10-27
        相关资源
        最近更新 更多