2017-02-15 21 views
2

我想創建一個程序,它會根據「實時」接收到的數據以任何方式對橢圓進行着色。數據是這樣的:x1-1,x2-1從WPF的串口接收數據時做點什麼

我有一個奇怪的問題,我可以在調試時看到,填充橢圓的顏色應該改變,但它不會發生。我與接收數據的代碼

部分:

private void ReceiveData() 
      { 
       SerialPort serialPort = new SerialPort("COM1", 9600); 
       serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); 
       serialPort.Open(); 
      } 

private static void DataReceivedHandler(
       object sender, 
       SerialDataReceivedEventArgs e) 
      { 
       SerialPort sp = (SerialPort)sender; 
       string indata = sp.ReadExisting(); 
       if (indata.Contains(" ")) 
       { 
        testString = indata.Substring(0, 4); 

       } 
       Console.Write(indata); 
      } 

我可以看到在收到控制檯數據,甚至點擊按鈕後,啓動接收數據。 testString將從indata中提取單個x1-1,這在接收數據期間仍然在增長。我知道它不會像它應該那樣工作,但現在並不重要。行動按鈕

代碼:

private void button1_Click(object sender, RoutedEventArgs e) 
     { 
      ReceiveData(); 
      while (true) 
      { 
       if (testString == "x1-1") x1.Fill = Brushes.Blue; 
       else x1.Fill = Brushes.Red; 
      } 
     } 

x1是橢圓形,我想使紅色或藍色。我可以在這個函數中設置斷點,我可以看到它應該改變。我認爲問題在於,該程序正在等待關閉端口並完成傳輸,然後可能會改變,但我需要「實時」。任何人都知道如何做到這一點?

+0

顯示美國'Console.Write(的TestString);' –

+0

第一次迭代是空的,但那麼它通常看起來像'x1-1','x2-1' – Vades

+0

如果你把一個斷點在你的「如果'語句,teststring是否等於'x1-1'?如果是這樣,你的UI線程永遠不會得到重繪的機會,因爲你正在做'while(true)'......你在錘擊CPU。它對你自己來說 - 打開任務管理器,看看內核是否達到100%,考慮在每300-500ms執行一次的計時器上更新UI,這將給UI線程做好工作的機會 –

回答

1

我相信你會這樣做是錯誤的。您不必經常檢查teststring的值,而只需啓動通信端口偵聽器並讓它在後臺運行 - 因爲這將在它自己的線程上運行。然後你需要創建一個數據綁定到顏色。每當通信端口偵聽器分析一個字符串時,它就會自動更新顏色。

首先,在CommPort的類:

class MyCommPort : INotifyPropertyChanged 
{ 
    SerialPort serialPort = null; 
    public MyCommPort() 
    { 
     serialPort = new SerialPort("COM3", 9600); 
     serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); 
     serialPort.Open(); 
    } 
    ~MyCommPort() 
    { 
     serialPort.Close(); 
    } 

    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
    { 
     SerialPort sp = (SerialPort)sender; 
     string testString = null; 
     string indata = sp.ReadLine(); 
     if (indata.Length >= 4) 
     { 
      testString = indata.Substring(0, 4); 
      // Update the value 
      if (testString == "x1-1") EllipseBrush = Brushes.Blue; 
      else EllipseBrush = Brushes.Red; 
     } 
     Console.Write(testString); 
    } 

    // Create a property that will be bound 
    private SolidColorBrush ellipseBrush = Brushes.Red; 
    public SolidColorBrush EllipseBrush 
    { 
     get { return ellipseBrush; } 
     set 
     { 
      ellipseBrush = value; 
      OnPropertyChanged("EllipseBrush"); 
     } 
    } 

    // Extend the INotifyPropertyChanged interface 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      // Alert anyone bound to this that the value has changed 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

然後,將橢圓的的DataContext到CommPort的類和綁定橢圓的Fill屬性EllipseBrush。 現在您只需啓動Commport監聽器(ReceiveData();),顏色更新應自動進行。

例如:MainWindow.xaml

<Window x:Class="delete_me.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> 
     <Ellipse x:Name="ellipse" Fill="{Binding Path=EllipseBrush}" /> 
    </Grid> 
</Window> 

而後面的代碼:MainWindow.xaml.cs

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     ellipse.DataContext = new MyCommPort(); 
    } 
} 
+0

這部分代碼有問題: 'if(testString ==「x1-1」)EllipseBrush = Brushes.Blue; else EllipseBrush = Brushes.Red;' 因爲EllipseBrush在這個靜態上下文中無法在這個地方使用 – Vades

+0

您可以從函數中移除'static'。我已經更新了答案。此外,我只寫了一個測試應用程序,這個工程。 –

+0

很高興知道。那麼,謝謝。我會盡力做到明天,我必須找到信息如何讓你在代碼下面寫下你所寫的內容,因爲它對我來說並不那麼明顯。 – Vades

0

不要由具有while(true)點擊一個按鈕的內掛UI線程事件。改爲使用DispatchTimer每500秒執行一次工作。

System.Windows.Threading.DispatcherTimer MyTimer = null; 
private void ReceiveData() 
{ 
    MyTimer = new System.Windows.Threading.DispatcherTimer(); 
    MyTimer.Interval = new TimeSpan(0, 0, 0, 0, 500); 
    MyTimer.Tick += MyTimer_Tick; 
    MyTimer.Start(); 
    SerialPort serialPort = new SerialPort("COM1", 9600); 
    serialPort.DataReceived += new 
      SerialDataReceivedEventHandler(DataReceivedHandler); 
    serialPort.Open(); 
} 

private static void DataReceivedHandler(
       object sender, 
       SerialDataReceivedEventArgs e) 
{ 
    SerialPort sp = (SerialPort)sender; 
    string indata = sp.ReadExisting(); 
    if (indata.Contains(" ")) 
    { 
     testString = indata.Substring(0, 4); 

    } 
} 

private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    ReceiveData(); 
} 

private void MyTimer_Tick(object sender, EventArgs e) 
{ 
    if (testString == "x1-1") 
    { 
     x1.Fill = Brushes.Blue; 
    } 
    else 
    { 
     x1.Fill = Brushes.Red; 
    } 
} 
+0

'EllipseBrush = Brushes.Blue;'和'x1.Fill = Brushes.Blue'有什麼區別?使用'EllipseBrush = Brushes.Blue;'它不能被編譯,因爲缺少聲明,'x1.Fill = Brushes.Blue'它仍然不起作用。 – Vades

+0

但它仍然無法正常工作。該錯誤必須在其他地方。 – Vades

+0

我編輯了Timer_Tick事件中的代碼。如果您將其更新爲我所擁有的,並且斷點代碼,並進入它,您會看到什麼發生? –

相關問題