C# 使用Arduino期间的WPF数据绑定
我正在用C#和Arduino开发一个应用程序。我从Arduino读取值并在文本框中设置值。我希望始终从Arduino读取值并在界面上设置。但是此代码不起作用。 我应该在不同的线程中运行while语句吗 这是我的密码C# 使用Arduino期间的WPF数据绑定,c#,wpf,arduino,C#,Wpf,Arduino,我正在用C#和Arduino开发一个应用程序。我从Arduino读取值并在文本框中设置值。我希望始终从Arduino读取值并在界面上设置。但是此代码不起作用。 我应该在不同的线程中运行while语句吗 这是我的密码 SerialPort port = new SerialPort("COM4", 9600); port.Open(); while (true) { String s=port.ReadLine();
SerialPort port = new SerialPort("COM4", 9600);
port.Open();
while (true)
{
String s=port.ReadLine();
txtValue.Text=s;
}
port.Close();
}
我希望从Arduino读取的显示值同时显示在文本框中。这是要启动的代码(将其放入构造函数、加载的窗口或按钮单击事件中):
这是要停止的代码(将其放入窗口<代码>关闭代码>事件):
这不使用任何绑定,但应能让您了解如何组织端口操作(带或不带绑定)。我无法与arduino方面交谈,但如果您使用的是.net 4.0或4.5,您可以执行以下操作:
Task myTask = Task.Factory.StartNew(() => {
while (true)
{
String s=port.ReadLine();
txtValue.Text=s;
}
});
正如Sinatr所提到的,确保有办法停止执行。您可以通过设置VARABLE而不是使用“true”来实现这一点。至于将代码放在哪里,这实际上取决于最终的程序 使用,您应该能够使用Arduino串行消息快速创建可观察的绑定
下面是一个基本的viewmodel类:
public class MainViewModel : GalaSoft.MvvmLight.ViewModelBase, IObserver<string>
{
#region Fields
private string _lastSerialMessageReceived;
private readonly ObservableCollection<string> _serialMessages = new ObservableCollection<string>();
#endregion
#region Constructors
public MainViewModel()
{
var connection = new Solid.Arduino.SerialConnection("COM3", Solid.Arduino.SerialBaudRate.Bps_115200);
var session = new Solid.Arduino.ArduinoSession(connection);
session.CreateReceivedStringMonitor().Subscribe(this);
}
#endregion
#region Public Interface
public void OnCompleted()
{
throw new NotImplementedException();
}
public void OnError(Exception error)
{
throw new NotImplementedException();
}
public void OnNext(string value)
{
_serialMessages.Add(value);
LastSerialMessageReceived = value;
}
public ObservableCollection<string> SerialMessages
{
get { return _serialMessages; }
}
public string LastSerialMessageReceived
{
get { return _lastSerialMessageReceived; }
private set { Set(() => LastSerialMessageReceived, ref _lastSerialMessageReceived, value); }
}
#endregion
}
public类主视图模型:GalaSoft.MvvmLight.ViewModelBase,IObserver
{
#区域字段
私有字符串\u lastSerialMessageReceived;
私有只读ObservableCollection _serialMessages=新ObservableCollection();
#端区
#区域构造函数
公共主视图模型()
{
var连接=新的Solid.Arduino.SerialConnection(“COM3”,Solid.Arduino.SerialBaudRate.bps115200);
var会话=新的Solid.Arduino.ArduinoSession(连接);
会话.CreateReceivedStringMonitor().Subscribe(此);
}
#端区
#区域公共接口
未完成的公共无效()
{
抛出新的NotImplementedException();
}
公共无效OnError(异常错误)
{
抛出新的NotImplementedException();
}
public void OnNext(字符串值)
{
_serialMessages.Add(value);
LastSerialMessageReceived=值;
}
公共ObservableCollection串行消息
{
获取{return\u serialMessages;}
}
已接收公共字符串LastSerialMessage
{
获取{return\u lastSerialMessageReceived;}
私有集{set(()=>LastSerialMessageReceived,ref _LastSerialMessageReceived,value);}
}
#端区
}
您可以将文本框绑定到属性LastSerialMessageReceived。属性SerialMessages可以绑定到列表框。在给定的代码段中,您没有从Arduino读取值。我更正了它,但仍然不起作用。可能是因为while语句。我希望同时在文本框中显示值。如果给定的代码段在UI线程中运行,那么它将阻止它,并且您看不到任何txtValue
更改。你必须以不同的方式组织它。创建并运行任务
(或线程
),在其中打开com端口并开始读取。当您想要更新txtValue
-它。别忘了提供一个安全机制来停止任务(不要中止线程)并关闭com端口,例如,在窗体关闭时设置一些变量,在中不断检查此变量,同时将中断它。我应该在构造函数中调用线程还是在其他位置调用线程?我强烈建议使用MVVM模式,它将使您的生活更加轻松。使用MVVM,您不必将大多数代码移动到UI线程上以更新显示。
Task myTask = Task.Factory.StartNew(() => {
while (true)
{
String s=port.ReadLine();
txtValue.Text=s;
}
});
public class MainViewModel : GalaSoft.MvvmLight.ViewModelBase, IObserver<string>
{
#region Fields
private string _lastSerialMessageReceived;
private readonly ObservableCollection<string> _serialMessages = new ObservableCollection<string>();
#endregion
#region Constructors
public MainViewModel()
{
var connection = new Solid.Arduino.SerialConnection("COM3", Solid.Arduino.SerialBaudRate.Bps_115200);
var session = new Solid.Arduino.ArduinoSession(connection);
session.CreateReceivedStringMonitor().Subscribe(this);
}
#endregion
#region Public Interface
public void OnCompleted()
{
throw new NotImplementedException();
}
public void OnError(Exception error)
{
throw new NotImplementedException();
}
public void OnNext(string value)
{
_serialMessages.Add(value);
LastSerialMessageReceived = value;
}
public ObservableCollection<string> SerialMessages
{
get { return _serialMessages; }
}
public string LastSerialMessageReceived
{
get { return _lastSerialMessageReceived; }
private set { Set(() => LastSerialMessageReceived, ref _lastSerialMessageReceived, value); }
}
#endregion
}