【问题标题】:How to get data from a classes data received event to MainWindow to update the UI如何从类数据接收事件中获取数据到 MainWindow 以更新 UI
【发布时间】:2019-05-08 13:46:25
【问题描述】:

我正在创建一个程序,它从连接到 3 个不同传感器的 Arduino 读取 .csv 数据。 此数据从 Serial 类读取并发送到 ParseData 类,该类将 .csv 数据添加到 List 和 将其发送到每个传感器的 3 个类。 (所有三个传感器的数据同时从 Arduino 发送并从 ParseData 类解析)

三个类:Sensor1、Sensor2、Sensor3

数据模型:SensorDataModel1、SensorDataModel2、SensorDataModel3

我想用三个不同类的数据更新 MainWindow.xaml/MainWindow.xaml.cs 中的图表作为图表上的一条线。我想在 MainWindow 中收到这三个传感器有新数据的通知,然后用数据更新图表。我不确定我是否必须为每个传感器或类似的东西订阅一个事件。

// SerialCommunication.cs - read in data and send to ArduinoDataReceived() method for parsing
private void OnDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    try
    {
        SerialPort sp = (SerialPort)sender;
        string serialBuffer = sp.ReadLine();

        // Send the subscriber the data received
        if (DataReceived != null)
        {
            DataReceived?.Invoke(this, new SerialDataReceivedEventArgs()
            {
                dataReceived = serialBuffer
            });
        }
    }
    catch (Exception ex) { MessageBox.Show(ex.ToString()); }
}


// ParseData.cs - subscribed to SerialCommunication.cs event and receives the data string and sends data to each sensors class
private void ArduinoDataReceived(object sender, SerialDataReceivedEventArgs e)
{
    Sensor1 sensor1 = new Sensor1();
    Sensor2 sensor2 = new Sensor2();
    Sensor3 sensor3 = new Sensor3();

    // parse all sensor data from Arduino to a list which holds all three sensors data
    List<string> sensorData = e.ToString().Split(',').ToList();

    // parse list for each sensor and send off to each class to process the data
    sensor1.AddData(sensorData1);
    sensor2.AddData(sensorData2);
    sensor3.AddData(sensorData3);
}


// SensorData1.cs - an example of storing the data and adding it to a List of the Sensors data model
public List<SensorDataModel1> ListSensorData1 = new List<SensorDataModel1>();

public void AddData(List<string> data, long dataLength)
{
    SensorDataModel1 s1 = new SensorDataModel1();

    s1.Add(data[0]);
    s1.Add(data[1]);
    s1.Add(data[2]);

    ListSensorData1.Add(s1);
}

我希望所有三个 Data 类都将数据发送回 MainWindow,并让 MainWindow 在每次从串行端口读取这些值时使用这些值更新图表。

【问题讨论】:

  • 您想要 MainWindow ViewModel 或后面的代码,无论您使用哪个类来拥有每个类的实例并订阅它们更新/接收的方法,然后使用它作为重绘/将信息添加到您的图表中。
  • 感谢您的评论。我在 MainWindow 中的每个类都有一个实例,所有三个类都有一个 AddData() 方法来更新列表,但我在这些类中没有任何事件要订阅?
  • 也许 SerialCommunication 类中有什么东西?
  • 所以我应该改变我的架构,在我的解析数据类中订阅串行接收事件,然后我应该通过事件而不是调用和 AddData() 方法将数据传递给每个传感器类?我认为某种 INotifyPropertyChanged 或 ObservableCollection 可以解决我的问题,但我不太确定如何实现它
  • 您回复的后半部分似乎是个不错的尝试。为每个传感器在您的类上创建 3 个属性,propfull 代码 sn-p 会有所帮助,然后让您的类实现 INotifyPropertyChanged 并且每个属性都在集合上调用它,docs.microsoft.com/en-us/dotnet/api/… 应该可以帮助您弄清楚如何实现它.

标签: c# wpf xaml mvvm data-binding


【解决方案1】:

在不知道您的整个架构是如何设置的情况下,我只能假设。在您的情况下,我最有可能做的是:

1) 让您的主窗口订阅SerialDataReceivedEventArgs,以便在主窗口后面的代码中引发事件。 This question 应该是一个很好的起点。这将允许您从主窗口更新数据。

2) 如果您正在使用视图模型并绑定数据;然后我会创建一个命令或方法来将新的传感器数据添加到您的集合中。在您的视图模型中,我将为每个传感器创建一个ObservableCollection,然后使用绑定将它们附加到主窗口。

//MainWindow XAML
<Window.DataContext>
    <vm:MainWindowViewModel/>
</Window.DataContext>
<YourControl1 ItemSource={Binding Source=SensorData1}/>
<YourControl2 ItemSource={Binding Source=SensorData2}/>
<YourControl3 ItemSource={Binding Source=SensorData3}/>

3) 在后面的 MainWindow 代码中(或者在 XAML 中,如果你想创建新的事件)你可以调用 ViewModel 命令或方法来更新数据。使用上面链接中的名称:

// inside MainWindow.xaml.cs
private void DisplaySerDataHandler(object sender, SerialDataReceivedEventArgs e)
{
   var newSensorData1;
   //...This is where you set all the new sensor data you received to the variables. 
   var dContext = DataContext as MainWindowViewModel;
   dContext?.SetNewSensorData(newSensorData1, newSensorData2, newSensorData3);
}

4) 在 MainWindowViewModel.cs 中,您可以使用业务逻辑来更改 ObservableCollections,当添加到 UI 元素时会更新并自动更新 UI 元素。

//you need an ObservableCollection for each list
public ObservableCollection<sensorType> SensorData1 {get;set;}

//then create the command or method to add the data to their respective Collection
public void SetNewSensorData(sensorType sData1, sensorType sData2, sensorType sData3){

  //...then add the new data (with extra logic as needed)
  SensorData1.add(sData1);
  SensorData2.add(sData2);
  SensorData3.add(sData3);
}

还有许多其他可以/应该完成的元素。这是一个示例,说明如何使用传入的序列化数据更新主窗口控件。如何设计一切取决于您。你的MainWindowViewModel 将实现INotifyPropertyChanged。我更喜欢使用命令,因为我可以尝试从后面的代码中删除代码并在 XAML 中绑定所有内容,然后我的所有逻辑都可以包含在 ViewModel 中。这不是正确或错误的做法,只是我的偏好。我更喜欢后面的代码仅用于专门更改 Control 元素本身,所有其他业务逻辑都在 ViewModel 中。

【讨论】:

  • 抱歉回复晚了。这是一个很好的答案,对我帮助很大。在查看了这个并获得了更多关于 MVVM 的知识之后,我已经完全从后面的代码中删除了我的代码,我目前正在实现命令,谢谢。
猜你喜欢
  • 2019-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-10
  • 2011-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多