【问题标题】:c# Passing parameters on event from another class to main classc#将事件的参数从另一个类传递到主类
【发布时间】:2014-05-07 10:00:22
【问题描述】:

我有一个主 (Form1) 类和一个处理所有串行通信 (ComPort) 的第二类

当通过串行端口(事件)接收到新数据时,我想将其传递给 Form1 并对这些数据进行一些操作。 小例子:根据接收到的数据创建长字符串

Form1.cs

public partial class Form1 : Form  
{  
//Creating instance of SerialCommunication.
....
....
string receivedString = ""; //Here I will store all data

public void addNewDataMethod(string newDataFromSerial)
{ 
  receivedString = receivedString + newDataFromSerial;
  MessageBox.Show(receivedString);
}

}

SerialCommunication.cs

public partial class SerialCommunicationPort   
    {  
      constructor()  
      {      
       .... //open serial port with the relevant parameters  
       ComPort.DataReceived += new SerialDataReceivedEventHandler(ComPortBufferRead);//Create Handler  
      }  
     public void ComPortBufferRead(object sender, SerialDataReceivedEventArgs e)  
     {  
      //create array to store buffer data  
      byte[] inputData = new byte[ComPort.BytesToRead];  
      //read the data from buffer  
      ComPort.Read(inputData, 0, ComPort.BytesToRead);  

    //*****  What should I write here in order to  pass "inputData" to Form1.addNewDataMethod ?


    }  
  }

我尝试了以下方法:

Form1 Form;  
Form1.addNewDataMethod(inputData.ToString());

以上代码会产生错误:use of unassigned local variable "Form"

Form1 Form1 = new Form1(); 
Form1.addNewDataMethod(inputData.ToString());

上面会创建一个新的Form1实例,并且不会包含之前接收到的数据。

有什么建议吗?

【问题讨论】:

    标签: c# winforms class events


    【解决方案1】:

    SerialCommunication 类中创建一个事件,该事件将在数据到达时引发:

    public partial class SerialCommunicationPort   
    { 
        public event Action<byte[]> DataReceived;
    
        public void ComPortBufferRead(object sender, SerialDataReceivedEventArgs e)  
        {       
           byte[] inputData = new byte[ComPort.BytesToRead];  
           ComPort.Read(inputData, 0, ComPort.BytesToRead);  
    
           if (DataReceived != null)
               DataReceived(inputData);
        }  
    }
    

    然后在您的表单中订阅此事件。

    public partial class Form1 : Form  
    {  
        SerialCommunication serialCommunication;
    
        public Form1()
        {
            InitializeComponent();
            serialCommunication = new SerialCommunication();
            serialCommunication.DataReceived += SerialCommunication_DataReceived;
        } 
    
        private void SerialCommunication_DataReceived(byte[] data)
        {
            // get string from byte array 
            // and call addNewDataMethod
        }
    }
    

    如果您想遵循 Microsoft 的 WinForms 编码指南,那么您应该使用 EventHandler&lt;DataReceivedEventArgs&gt; 委托而不是 Action&lt;byte[]&gt; 委托,其中 DataReceivedEventArgs 是继承自 EventArgs 的类。

    【讨论】:

    • 谢谢,我会试试的。为什么需要“if (DataReceived !=null)”?
    • @orenk 与 VB.NET 不同,当您尝试引发没有处理程序的事件时,C# 将抛出 NullReferenceException,因此您需要在引发之前检查是否有人订阅了事件
    • 请注意,对于 c# 6,可以使用空条件运算符 DataReceived?.Invoke(inputData); 简化此空检查
    【解决方案2】:

    可能最好的方法是使用事件。定义一个事件,该事件将采用一个字符串的 EventArgs 参数。在 Form1 中订阅事件并在您的串行通信类中触发事件,将您想要的字符串传递给 eventargs。

    你想要的方式应该也可以,但是像这样:

    Form1 Form = new Form1();  
    Form.Show(); // to display it...
    /// to other stuff...
    Form.addNewDataMethod(inputData); // call the method on the INSTANCE which you opened!
    

    类似于方法的使用,你可以在 Form1 中定义一个属性:

    private string _myString = "";
    public string MyString {
        private get {   
    }
    set {
        string _myString= value;
       // to with the string what you want
    }
    }
    

    然后类似方法调用使用

    Form.MyString = "abc";
    

    希望对您有所帮助!

    【讨论】:

    • 这里的问题是当我使用“Form1 Form = new Form1();”时它将创建一个新的空Form1,我将无法访问原始Form1中已经存储的数据(我试过了)
    • 为什么要多次调用 new Form1() ?!?!?使用 Form1 Form = new Form1() 打开一次;并在使用参考(表单)之后。
    • 我首先在表单中填写一些数据和串行参数,然后使用这些参数创建一个 SerialPort 实例。在用户已经输入了一些其他数据之后,我无法使用新创建的 FORM1。 (串口参数除外)。你的建议很好如果我想使用 Form1 方法而不操纵现有数据(可能从不同的类收集)
    猜你喜欢
    • 2021-04-24
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多