我正在尝试从串口读取并将数据放入网格中。 并且数据不会出现在数据网格中。
我在下面使用了每个马丁评论的通知更换器。
仅在串行端口更新时显示数据网格视图上的数据。
这是xaml:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="689.7" Width="655">
<Grid Margin="0,0,2,9">
<DataGrid x:Name="DataGridData" Margin="50,25,19,10" AutoGenerateColumns="False" ItemsSource="{Binding Source=FirstName}">
</DataGrid>
</Grid>
</Window>
这是CS:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.Ports;
using System.Threading;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
/// <summary>
/// this class contain a row for the data to show in the dataGridRecieved
/// </summary>
public class DataForTable : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private string time; // contain the time of the data that has been sent or recieved.
/// <summary>
/// get or sets the time that has been recieved.
/// </summary>
public string Time
{
get { return time; }
set { time = value;
PropertyChanged(this, new PropertyChangedEventArgs("Time"));
}
}
private string data; // contain the line of data the has been recieved.
/// <summary>
/// get or set the line of data that has been send to recieved
/// </summary>
public string Data
{
get { return data; }
set { data = value;
PropertyChanged(this, new PropertyChangedEventArgs("Data"));
}
}
}
private System.Threading.Thread threadSerial;
private System.IO.Ports.SerialPort _sp;
private Queue<byte[]> _QbytesFromSerialPort1;
private Queue<DateTime> _QDateTimeFromSerialPort1;
private byte[] _RealBytesFromSerialPort;
private delegate void emptydelagte(); // delegate to pass on the play option.
private emptydelagte updateTableGuiDelgate;
public DataForTable _dataForTable;
private Thread GUIThread;
object lockMessage;
private ObservableCollection <DataForTable> _firstName;
public ObservableCollection<DataForTable> FirstName
{
get { return _firstName; }
set { _firstName = value;
PropertyChanged(this, new PropertyChangedEventArgs("Items"));
}
}
public MainWindow()
{
InitializeComponent();
_QbytesFromSerialPort1 = new Queue<byte[]>();
_QDateTimeFromSerialPort1 = new Queue<DateTime>();
_firstName = new ObservableCollection<DataForTable>();
_dataForTable = new DataForTable();
// DataGridData.ItemsSource = _firstName.Select(DataForTable => new { DataForTable.Data, DataForTable.Time }).ToList();
//create serial port
_sp = new SerialPort("COM1", 38400, Parity.None, 8, StopBits.One);
_sp.Open();
threadSerial = new Thread(new ThreadStart(readSerialPort)); //reads from serial port.
threadSerial.IsBackground = true;
threadSerial.Start();
//updateTableGuiDelgate = new emptydelagte(updateTableGuiDelgate);
GUIThread = new Thread(new ThreadStart(GuIThread));
GUIThread.IsBackground = true;
GUIThread.Start();
}
private void readSerialPort()
{
_RealBytesFromSerialPort = new byte[100];
DateTime _dtRead = new DateTime();
lockMessage = 0;
while (true)
{
if (_sp.IsOpen)
{
if (_sp.BytesToRead > 0)
{
lock (lockMessage)
{
_RealBytesFromSerialPort = new byte[_sp.BytesToRead];
_sp.Read(_RealBytesFromSerialPort, 0, _sp.BytesToRead); //read data
if (_RealBytesFromSerialPort.Length != 0)
{
_dtRead = DateTime.Now;
_QbytesFromSerialPort1.Enqueue(_RealBytesFromSerialPort); // q from serial porta
_QDateTimeFromSerialPort1.Enqueue(_dtRead); // q from date time now.
}
}
}
}
}
}
private byte[] tmp;
private void GuIThread()
{
_dataForTable = new DataForTable();
while (true)
{
if (_QbytesFromSerialPort1.Count > 0)
{
_dataForTable.Data = byteToString(_QbytesFromSerialPort1.Dequeue());
_dataForTable.Time = DateTime.Now.ToLongDateString();
_firstName.Add(_dataForTable);
// this.Dispatcher.BeginInvoke(updateTableGuiDelgate);
}
}
}
private string byteToString(byte [] arr)
{
string tmps = "";
for (int i = 0; i < arr.Length; i++)
{
tmps += arr[i].ToString() + " ";
}
return tmps;
}
}
}
答案 0 :(得分:0)
以下是如何从另一个线程添加数据的示例:
<Window x:Class="DatagridBInding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid ItemsSource="{Binding Items}"/>
</Grid>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<DataTableItem> _Items;
public ObservableCollection<DataTableItem> Items
{
get { return _Items; }
set
{
_Items = value;
PropertyChanged(this, new PropertyChangedEventArgs("Items"));
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
Items = new ObservableCollection<DataTableItem>();
Task.Factory.StartNew(() =>
{
Dispatcher.Invoke(() =>
{
for (int i = 0; i < 10; i++)
Items.Add(new DataTableItem() { Data = "Data " + i });
}
);
});
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
DataTableItem类:
public class DataTableItem : INotifyPropertyChanged
{
private string _Data;
public string Data
{
get { return _Data; }
set
{
_Data = value;
PropertyChanged(this, new PropertyChangedEventArgs("Data"));
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
为了让UI被告知添加的新项目,您需要使用ObservableCollection而不是那个简单的List。
还有一件事,SerialPort类有一个DataReceived事件,这不是更适合这里而不是轮询吗?
此外,尝试简化回到GUI线程的方式,它有点难以遵循,它不应该。在我的例子中,我在Invoke上使用了lambda表达式。看看吧!