读取串口后如何DataBind DataBrid

时间:2015-09-21 07:54:56

标签: c# wpf xaml data-binding serial-port

我正在尝试从串口读取并将数据放入网格中。 并且数据不会出现在数据网格中。

我在下面使用了每个马丁评论的通知更换器。

仅在串行端口更新时显示数据网格视图上的数据。

这是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;
     }
    }
 }

1 个答案:

答案 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表达式。看看吧!