从 Blazor 上的串口读取
Read from Serial Port on Blazor
我是 Blazor 的新手,我正在尝试创建一个从串行端口读取的应用程序。
首先,我使用 .Core 3.1 创建了一个控制台应用程序
一切正常,所以我将代码移至 Blazor,尽管当我放置调试点时我可以看到代码有效,但我无法使 UI 显示值
@using System;
@using System.Diagnostics;
@using System.IO.Ports;
@using System.Threading;
<head>
<title>Main Scale Monitor</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/css/all.css" rel="stylesheet">
<link href="/css/stylesheet.css" rel="stylesheet">
</head>
<div class="scale-monitor">
<div class="digital-monitor net-weight grid-line">
<div class="digital-monitor-left net-left">NET</div>
<div class="digital-monitor-center net-center" bind="@ScaleValue"></div>
<div class="digital-monitor-right net-right">Kg</div>
</div>
</div>
@code {
public string ScaleValue { get; set; } = "0.001";
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
System.IO.Ports.SerialPort mySerialPort = new System.IO.Ports.SerialPort("COM3");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = System.IO.Ports.Parity.None;
mySerialPort.StopBits = System.IO.Ports.StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = System.IO.Ports.Handshake.None;
mySerialPort.NewLine = (@"&N");
mySerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedHandler);
if (!mySerialPort.IsOpen)
{
mySerialPort.Open();
}
}
}
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
try
{
string indata = sp.ReadLine();
ScaleValue = indata.ToString(); //WHEN I PUT DEBUG HERE I CAN SEE THE CORRECT VALUE
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
}
<style>
*, ::after, ::before {
box-sizing: unset;
}
.grid-line {
border: 1px solid black;
}
.scale-monitor {
display: grid;
grid-template-columns: 35% 35% 30%;
grid-template-rows: 50% 50%;
width: 100%;
height: 90%;
margin: 5px;
width: 1020px;
}
/*#region generic*/
.digital-monitor {
background: #000000;
color: greenyellow;
text-align: right;
font-family: digitalregular;
display: grid;
grid-template-columns: repeat(10, 1fr);
grid-template-rows: repeat(5, 1fr);
width: 95%;
height: 95%;
margin: 5px;
border-radius: 15px;
align-items: center;
}
/*#region generic scalemonitor*/
.digital-monitor-left {
writing-mode: vertical-rl;
opacity: 0.5;
grid-row: 1 / span 5;
grid-column: 1;
text-align: center;
grid-column: 1;
transform: rotate(180deg);
}
.digital-monitor-center {
grid-row: 2 / span 3;
grid-column: 2/ span 7;
text-align: right;
vertical-align: bottom;
}
.digital-monitor-right {
grid-row: 2 / span 3;
grid-column: 9/ span 2;
text-align: right;
opacity: 0.75;
margin-bottom: 0.4em;
margin-right: 3px;
align-self: self-end;
}
/*#endregion*/
/*#endregion*/
/*#region NET*/
.net-weight {
grid-column: 2;
grid-row: 1 / span 2;
height: 98%;
}
.net-left {
font-size: 40px;
}
.net-center {
font-size: 100px;
}
.net-right {
font-size: 40px;
}
/*#endregion NET*/
</style>
知道如何正确绑定吗?
来自 Blazor 生命周期 documentation:
“渲染后立即进行的异步工作必须在 OnAfterRenderAsync 生命周期事件期间发生。
即使您 return 来自 OnAfterRenderAsync 的任务,框架也不会在该任务完成后为您的组件安排进一步的渲染周期。这是为了避免无限渲染循环。它不同于其他生命周期方法,后者会在 returned 任务完成后安排进一步的渲染周期。"
尝试在 ScaleValue
设置后手动调用 StateHasChanged()
。
您的问题出在您尝试将值绑定到 div。
div
元素不是组件,不支持绑定属性。
试试这个:<div class="digital-monitor-center net-center">@ScaleValue</div>
由于您的代码不依赖于页面的呈现,请将其设置为使用另一种生命周期方法。
试着把它放在protected override void OnInitialized() { }
编辑:
在此处阅读 Blazor 的生命周期:https://docs.microsoft.com/en-us/aspnet/core/blazor/lifecycle?view=aspnetcore-3.1
编辑:代码示例
@using System;
@using System.Diagnostics;
@using System.IO.Ports;
@using System.Threading;
@page "/Test";
<head>
<title>Main Scale Monitor</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/css/all.css" rel="stylesheet">
<link href="/css/stylesheet.css" rel="stylesheet">
</head>
<div class="scale-monitor">
<div class="digital-monitor net-weight grid-line">
<div class="digital-monitor-left net-left">NET</div>
<div class="digital-monitor-center net-center">@ScaleValue</div>
<div class="digital-monitor-right net-right">Kg</div>
</div>
</div>
@code {
public string ScaleValue { get; set; } = "0.001";
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
}
}
protected override void OnInitialized()
{
System.IO.Ports.SerialPort mySerialPort = new System.IO.Ports.SerialPort("COM3");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = System.IO.Ports.Parity.None;
mySerialPort.StopBits = System.IO.Ports.StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = System.IO.Ports.Handshake.None;
mySerialPort.NewLine = (@"&N");
mySerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedHandler);
ScaleValue = "test";
//I skipped this part with a return, since I don't have COM3 locally
if (!mySerialPort.IsOpen)
{
mySerialPort.Open();
}
}
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
try
{
string indata = sp.ReadLine();
ScaleValue = indata.ToString(); //WHEN I PUT DEBUG HERE I CAN SEE THE CORRECT VALUE
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
}
<style>
*, ::after, ::before {
box-sizing: unset;
}
.grid-line {
border: 1px solid black;
}
.scale-monitor {
display: grid;
grid-template-columns: 35% 35% 30%;
grid-template-rows: 50% 50%;
width: 100%;
height: 90%;
margin: 5px;
width: 1020px;
}
/*#region generic*/
.digital-monitor {
background: #000000;
color: greenyellow;
text-align: right;
font-family: digitalregular;
display: grid;
grid-template-columns: repeat(10, 1fr);
grid-template-rows: repeat(5, 1fr);
width: 95%;
height: 95%;
margin: 5px;
border-radius: 15px;
align-items: center;
}
/*#region generic scalemonitor*/
.digital-monitor-left {
writing-mode: vertical-rl;
opacity: 0.5;
grid-row: 1 / span 5;
grid-column: 1;
text-align: center;
grid-column: 1;
transform: rotate(180deg);
}
.digital-monitor-center {
grid-row: 2 / span 3;
grid-column: 2/ span 7;
text-align: right;
vertical-align: bottom;
}
.digital-monitor-right {
grid-row: 2 / span 3;
grid-column: 9/ span 2;
text-align: right;
opacity: 0.75;
margin-bottom: 0.4em;
margin-right: 3px;
align-self: self-end;
}
/*#endregion*/
/*#endregion*/
/*#region NET*/
.net-weight {
grid-column: 2;
grid-row: 1 / span 2;
height: 98%;
}
.net-left {
font-size: 40px;
}
.net-center {
font-size: 100px;
}
.net-right {
font-size: 40px;
}
/*#endregion NET*/
</style>
我找到了答案,
我不是 100% 这是最好的解决方案
创建服务
public class ReadSerialPortService
{
public string SerialPortValue { get; set; }
public ReadSerialPortService()
{
System.IO.Ports.SerialPort mySerialPort = new System.IO.Ports.SerialPort("COM3");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = System.IO.Ports.Parity.None;
mySerialPort.StopBits = System.IO.Ports.StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = System.IO.Ports.Handshake.None;
mySerialPort.NewLine = (@"&N");
if (!mySerialPort.IsOpen)
{
mySerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedHandler);
mySerialPort.Open();
}
}
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
double scaleDec = 0.00;
try
{
string indata = sp.ReadLine();
SerialPortValue = indata.ToString();
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
public Task<string> GetSerialValue()
{
return Task.FromResult(SerialPortValue);
}
}
然后在组件中
@inject ReadSerialPortService _readSerialPortService
<head>
<title>Main Scale Monitor</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/css/all.css" rel="stylesheet">
<link href="/css/stylesheet.css" rel="stylesheet">
</head>
<div class="scale-monitor">
<div class="digital-monitor net-weight grid-line" @onclick="GetValue">
<div class="digital-monitor-left net-left">NET</div>
<div class="digital-monitor-center net-center">@ScaleValue</div>
<div class="digital-monitor-right net-right">Kg</div>
</div>
</div>
@code {
private int Count { get; set; } = 100;
Timer _updateTimer;
public string ScaleValue { get; set; } = "0.000";
protected override async Task OnInitializedAsync()
{
ScaleValue = await _readSerialPortService.GetSerialValue();
_updateTimer = new Timer(state => { InvokeAsync(GetValue); }, null, 0, 100);
}
public async Task GetValue()
{
ScaleValue = await _readSerialPortService.GetSerialValue();
await InvokeAsync(() => StateHasChanged());
}
public void Dispose()
{
_updateTimer.Dispose();
}
}
感谢您发帖。对我很有帮助。
我正在使用 .NET Core 3.1 构建 Blazor 应用程序。
"system.io.ports.serialport" 不包含在标准 .NET Core 中。它是一个扩展包。要安装,请查看此帖子 .
我是 Blazor 的新手,我正在尝试创建一个从串行端口读取的应用程序。 首先,我使用 .Core 3.1 创建了一个控制台应用程序 一切正常,所以我将代码移至 Blazor,尽管当我放置调试点时我可以看到代码有效,但我无法使 UI 显示值
@using System;
@using System.Diagnostics;
@using System.IO.Ports;
@using System.Threading;
<head>
<title>Main Scale Monitor</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/css/all.css" rel="stylesheet">
<link href="/css/stylesheet.css" rel="stylesheet">
</head>
<div class="scale-monitor">
<div class="digital-monitor net-weight grid-line">
<div class="digital-monitor-left net-left">NET</div>
<div class="digital-monitor-center net-center" bind="@ScaleValue"></div>
<div class="digital-monitor-right net-right">Kg</div>
</div>
</div>
@code {
public string ScaleValue { get; set; } = "0.001";
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
System.IO.Ports.SerialPort mySerialPort = new System.IO.Ports.SerialPort("COM3");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = System.IO.Ports.Parity.None;
mySerialPort.StopBits = System.IO.Ports.StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = System.IO.Ports.Handshake.None;
mySerialPort.NewLine = (@"&N");
mySerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedHandler);
if (!mySerialPort.IsOpen)
{
mySerialPort.Open();
}
}
}
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
try
{
string indata = sp.ReadLine();
ScaleValue = indata.ToString(); //WHEN I PUT DEBUG HERE I CAN SEE THE CORRECT VALUE
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
}
<style>
*, ::after, ::before {
box-sizing: unset;
}
.grid-line {
border: 1px solid black;
}
.scale-monitor {
display: grid;
grid-template-columns: 35% 35% 30%;
grid-template-rows: 50% 50%;
width: 100%;
height: 90%;
margin: 5px;
width: 1020px;
}
/*#region generic*/
.digital-monitor {
background: #000000;
color: greenyellow;
text-align: right;
font-family: digitalregular;
display: grid;
grid-template-columns: repeat(10, 1fr);
grid-template-rows: repeat(5, 1fr);
width: 95%;
height: 95%;
margin: 5px;
border-radius: 15px;
align-items: center;
}
/*#region generic scalemonitor*/
.digital-monitor-left {
writing-mode: vertical-rl;
opacity: 0.5;
grid-row: 1 / span 5;
grid-column: 1;
text-align: center;
grid-column: 1;
transform: rotate(180deg);
}
.digital-monitor-center {
grid-row: 2 / span 3;
grid-column: 2/ span 7;
text-align: right;
vertical-align: bottom;
}
.digital-monitor-right {
grid-row: 2 / span 3;
grid-column: 9/ span 2;
text-align: right;
opacity: 0.75;
margin-bottom: 0.4em;
margin-right: 3px;
align-self: self-end;
}
/*#endregion*/
/*#endregion*/
/*#region NET*/
.net-weight {
grid-column: 2;
grid-row: 1 / span 2;
height: 98%;
}
.net-left {
font-size: 40px;
}
.net-center {
font-size: 100px;
}
.net-right {
font-size: 40px;
}
/*#endregion NET*/
</style>
知道如何正确绑定吗?
来自 Blazor 生命周期 documentation: “渲染后立即进行的异步工作必须在 OnAfterRenderAsync 生命周期事件期间发生。
即使您 return 来自 OnAfterRenderAsync 的任务,框架也不会在该任务完成后为您的组件安排进一步的渲染周期。这是为了避免无限渲染循环。它不同于其他生命周期方法,后者会在 returned 任务完成后安排进一步的渲染周期。"
尝试在 ScaleValue
设置后手动调用 StateHasChanged()
。
您的问题出在您尝试将值绑定到 div。
div
元素不是组件,不支持绑定属性。
试试这个:<div class="digital-monitor-center net-center">@ScaleValue</div>
由于您的代码不依赖于页面的呈现,请将其设置为使用另一种生命周期方法。
试着把它放在protected override void OnInitialized() { }
编辑:
在此处阅读 Blazor 的生命周期:https://docs.microsoft.com/en-us/aspnet/core/blazor/lifecycle?view=aspnetcore-3.1
编辑:代码示例
@using System;
@using System.Diagnostics;
@using System.IO.Ports;
@using System.Threading;
@page "/Test";
<head>
<title>Main Scale Monitor</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/css/all.css" rel="stylesheet">
<link href="/css/stylesheet.css" rel="stylesheet">
</head>
<div class="scale-monitor">
<div class="digital-monitor net-weight grid-line">
<div class="digital-monitor-left net-left">NET</div>
<div class="digital-monitor-center net-center">@ScaleValue</div>
<div class="digital-monitor-right net-right">Kg</div>
</div>
</div>
@code {
public string ScaleValue { get; set; } = "0.001";
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
}
}
protected override void OnInitialized()
{
System.IO.Ports.SerialPort mySerialPort = new System.IO.Ports.SerialPort("COM3");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = System.IO.Ports.Parity.None;
mySerialPort.StopBits = System.IO.Ports.StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = System.IO.Ports.Handshake.None;
mySerialPort.NewLine = (@"&N");
mySerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedHandler);
ScaleValue = "test";
//I skipped this part with a return, since I don't have COM3 locally
if (!mySerialPort.IsOpen)
{
mySerialPort.Open();
}
}
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
try
{
string indata = sp.ReadLine();
ScaleValue = indata.ToString(); //WHEN I PUT DEBUG HERE I CAN SEE THE CORRECT VALUE
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
}
<style>
*, ::after, ::before {
box-sizing: unset;
}
.grid-line {
border: 1px solid black;
}
.scale-monitor {
display: grid;
grid-template-columns: 35% 35% 30%;
grid-template-rows: 50% 50%;
width: 100%;
height: 90%;
margin: 5px;
width: 1020px;
}
/*#region generic*/
.digital-monitor {
background: #000000;
color: greenyellow;
text-align: right;
font-family: digitalregular;
display: grid;
grid-template-columns: repeat(10, 1fr);
grid-template-rows: repeat(5, 1fr);
width: 95%;
height: 95%;
margin: 5px;
border-radius: 15px;
align-items: center;
}
/*#region generic scalemonitor*/
.digital-monitor-left {
writing-mode: vertical-rl;
opacity: 0.5;
grid-row: 1 / span 5;
grid-column: 1;
text-align: center;
grid-column: 1;
transform: rotate(180deg);
}
.digital-monitor-center {
grid-row: 2 / span 3;
grid-column: 2/ span 7;
text-align: right;
vertical-align: bottom;
}
.digital-monitor-right {
grid-row: 2 / span 3;
grid-column: 9/ span 2;
text-align: right;
opacity: 0.75;
margin-bottom: 0.4em;
margin-right: 3px;
align-self: self-end;
}
/*#endregion*/
/*#endregion*/
/*#region NET*/
.net-weight {
grid-column: 2;
grid-row: 1 / span 2;
height: 98%;
}
.net-left {
font-size: 40px;
}
.net-center {
font-size: 100px;
}
.net-right {
font-size: 40px;
}
/*#endregion NET*/
</style>
我找到了答案,
我不是 100% 这是最好的解决方案
创建服务
public class ReadSerialPortService
{
public string SerialPortValue { get; set; }
public ReadSerialPortService()
{
System.IO.Ports.SerialPort mySerialPort = new System.IO.Ports.SerialPort("COM3");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = System.IO.Ports.Parity.None;
mySerialPort.StopBits = System.IO.Ports.StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = System.IO.Ports.Handshake.None;
mySerialPort.NewLine = (@"&N");
if (!mySerialPort.IsOpen)
{
mySerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedHandler);
mySerialPort.Open();
}
}
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
double scaleDec = 0.00;
try
{
string indata = sp.ReadLine();
SerialPortValue = indata.ToString();
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
public Task<string> GetSerialValue()
{
return Task.FromResult(SerialPortValue);
}
}
然后在组件中
@inject ReadSerialPortService _readSerialPortService
<head>
<title>Main Scale Monitor</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/css/all.css" rel="stylesheet">
<link href="/css/stylesheet.css" rel="stylesheet">
</head>
<div class="scale-monitor">
<div class="digital-monitor net-weight grid-line" @onclick="GetValue">
<div class="digital-monitor-left net-left">NET</div>
<div class="digital-monitor-center net-center">@ScaleValue</div>
<div class="digital-monitor-right net-right">Kg</div>
</div>
</div>
@code {
private int Count { get; set; } = 100;
Timer _updateTimer;
public string ScaleValue { get; set; } = "0.000";
protected override async Task OnInitializedAsync()
{
ScaleValue = await _readSerialPortService.GetSerialValue();
_updateTimer = new Timer(state => { InvokeAsync(GetValue); }, null, 0, 100);
}
public async Task GetValue()
{
ScaleValue = await _readSerialPortService.GetSerialValue();
await InvokeAsync(() => StateHasChanged());
}
public void Dispose()
{
_updateTimer.Dispose();
}
}
感谢您发帖。对我很有帮助。
我正在使用 .NET Core 3.1 构建 Blazor 应用程序。
"system.io.ports.serialport" 不包含在标准 .NET Core 中。它是一个扩展包。要安装,请查看此帖子