【问题标题】:User Control to pass event back to parent form用户控件将事件传递回父表单
【发布时间】:2015-02-23 20:32:20
【问题描述】:

我有一个附有 3 个用户控件的主窗体。如何在不创建意大利面条代码的情况下让特定用户控件中的事件接触并修改其他两个用户控件的 UI?

主窗体(Form1.cs)

    public partial class Form1 : Form
   {
      private UserControl1 userControl11;
      private UserControl2 userControl21;
      private UserControl3 userControl31;

      public Form1()
      {
         InitializeComponent();
      }
   }

UserControl1.cs

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // Change buttons around and fill in some data on user control 2 and 3
    }

    private void button2_Click(object sender, EventArgs e)
    {
        // Remove certain elements from control2 and 3
    }

    // .. So forth
}

我将有许多事件在其他两个用户控件上执行许多不同的操作。我正在创建一个类似于 Visual Studio 的基本界面,我可以在其中打开项目、关闭它们、添加文件等。一个表单上的这些操作应该在其他控件中加载不同的窗口等。实现这一目标的最佳方法是什么?创建自定义事件并解析主窗体中的每个事件?还是直接从第一个用户控件访问每个用户控件?还是……?

【问题讨论】:

    标签: c# events delegates


    【解决方案1】:

    事件的一般模式是:

    public class MyClass{
    public static EventHanlder<ofSomeType> MyEventHandler;
    
    public void MyClass{
            MyEventHandler = _MyEventHandler;
    }
    public void _MyEventHandler(object sender, OfSomeType args){
          //do something with passed in args.
    }
    }
    

    其他类会像这样使用这些事件处理程序...

    public class myOtherClass{
       public void doSomething(){
          //do something here and signal the other class
          var ofSomeTypeData = GetData();        
          MyClass.MyEventHandler(ofSomeTypeData);        
       }
    }
    

    有些人会认为这种风格过于紧密地结合在一起,但它完美无缺,是一个好的开始。

    【讨论】:

    • 我遇到过这个问题并倾向于这个,但我的问题是它的紧密耦合性质。对于非紧密耦合的想法,您有什么基本的设计建议吗?
    • 是的,我想到了两种模式来打破紧密耦合的事件:1)使用中介模式,2)使用所谓的消息总线。这个概念是每个人都连接到调解器或消息总线,并且使用名称或其他众所周知的协议将消息“寻址”到侦听器。消息“停留”在队列中直到它被拾取,因此它也有助于松散耦合的工作流。最后还有另一件很酷的事情“反应式扩展”.....
    • 人们应该看看对ofSomeType的引用!现在非常方便的是,传递一个类型使得传递正确的参数成为可能:)。
    【解决方案2】:

    在每个 UserControl 中创建一个事件。 Form1 应该订阅这些控件上的事件。

    因此假设 UserControl1 允许用户对数据进行排序。那么你可以这样写:

    public Form1()
    {
       InitializeComponent();
       // I assume UserControl1 was created by this point
       userControl1.OnDataSorted = DataSorted;
    }
    
    // This will be called when the user wants to sort the data
    private void DataSorted(UserControl1 sender, EventArgs e)
    {
       // Change buttons around and fill in some data on user control 2 and 3
    }
    

    然后您将在 UserControl 中创建一个事件和一个委托。

    public class UserControl1 {
    
       public delegate void DataSortedDelegate(UserControl1 sender, EventArgs e);
    
       public event DataSorted OnDataSorted;
    
       private void button1_Click(object sender, EventArgs e)
       {
          if (OnDataSorted != null)
             OnDataSorted(this, EventArgs.Empty);
          // Replace EventArgs.Empty above with whatever data Form1 needs
       }
    

    这种方法在 Usercontrol1 和 Form1 之间创建了关注点分离。该控件不需要实际修改 Form1 内部的私有控件。它只是通知 Form1 发生了一些事情,并允许 Form1 进行更改。

    【讨论】:

    • 这没有意义。在UserControl1中,公共事件DataSorted OnDataSorted中的DataSorted是什么?
    猜你喜欢
    • 1970-01-01
    • 2010-10-07
    • 2021-06-13
    • 1970-01-01
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多