英文:
How to make Syncfusion gauge "NeedlePointer" value update on Property Change Event?
问题
I see that you're working with C# code to read data from a LoRa scanner and update a gauge with the received RSSI values. It seems like you're facing an issue where the gauge value doesn't update as expected.
One possible issue I noticed in your code is that when you're updating the Strength
property in the SerialPort_DataReceived
method, you are using the MainThread.BeginInvokeOnMainThread
to update the UI. However, in the ScannerConn_PropertyChanged
method, you are creating a new instance of HistoricalData
which won't have any connection to the UI.
To update the gauge value correctly, you should directly set the needlePointer.Value
and Number.Text
properties inside the ScannerConn_PropertyChanged
method without creating a new instance of HistoricalData
. Here's how you can modify the ScannerConn_PropertyChanged
method:
private void ScannerConn_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(scannerConn.Strength))
{
Device.BeginInvokeOnMainThread(() =>
{
needlePointer.Value = scannerConn.Strength;
Number.Text = scannerConn.Strength.ToString();
Debug.WriteLine("test1 " + needlePointer.Value);
Debug.WriteLine("test2 " + Number.Text);
});
}
}
Also, ensure that the ScannerConn_PropertyChanged
method is properly subscribed to the PropertyChanged
event of scannerConn
.
With these changes, the gauge should update correctly when new RSSI values are received.
英文:
I am reading data from a LoRa scanner utilizing SerialPort
that gets among other things, the signal strength (RSSI) that ranges between -10 and -110. I want the gauge to update automatically every time a new RSSI value is read.
I have created a serialPortConn
class where I connect to the scanner and read the data using a function named SerialPort_DataReceived
:
public void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
while (serialPort.BytesToRead > 0)
{
string DataIn = serialPort.ReadLine();
Debug.WriteLine("Data received from the scanner: " + DataIn);
// Process the received data and extract the fields
Network data = ProcessReceivedData(DataIn);
MainThread.BeginInvokeOnMainThread(() =>
{
// Check if the data name is not empty or null
if (!string.IsNullOrEmpty(data.Name))
{
// Find the existing network with the same name, if it exists
Network existingNetwork = NetworkNames.FirstOrDefault(network => network.Name == data.Name);
if (existingNetwork != null)
{
// Add the RSSI value to the existing network's RSSIList
// NetworkNames.Add(new Network { RSSI = data.RSSI });
// strength = data.RSSI;
Strength = data.RSSI;
existingNetwork.RSSI = data.RSSI;
existingNetwork.Name = data.Name;
Debug.WriteLine("strength: " + strength);
}
else
{
// Create a new network with the name and initialize its RSSIList
NetworkNames.Add(new Network { Name = data.Name, RSSI = data.RSSI });
// strength = data.RSSI;
Strength = data.RSSI;
}
// Print the network name and its RSSIList for debugging purposes
foreach (Network network in NetworkNames)
{
Debug.WriteLine("NetworkName: " + network.Name + " " + network.RSSI);
}
}
});
}
}
catch (OperationCanceledException)
{
// Handle the cancellation if needed
Debug.WriteLine("Reading data from the scanner was canceled.");
}
catch (Exception ex)
{
// Handle other exceptions
Debug.WriteLine($"Failed to read data from the scanner: {ex.Message}");
}
}
I am savig the new RSSI value to a strength
property defined at the beginning of the SerialPortConn
as follow:
public class SerialPortConn : INotifyPropertyChanged
{
//public ObservableCollection<Network> NetworkNames { get; set; }
private SerialPort serialPort;
Network networkNames = new Network();
public ObservableCollection<Network> NetworkNames { get; set; } = new ObservableCollection<Network>();
private int strength;
public int Strength
{
get { return strength; }
//get => strength;
set
{
if (strength != value)
{
strength = value;
OnPropertyChanged(nameof(Strength));
//OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
In the content page code behind, I am trying to assign the Strength
property to the NeedlePointer
value as follow:
namespace Scanner_MAUI.Pages;
public partial class HistoricalData : ContentPage, INotifyPropertyChanged
{
//public ObservableCollection<Network> NetworkNames { get; set; }
private SerialPortConn scannerConn;
public HistoricalData()
{
InitializeComponent();
needlePointer.Value = scannerConn.Strength;
Number.Text = scannerConn.Strength.ToString();
scannerConn.PropertyChanged += ScannerConn_PropertyChanged;
//..More Code
}
private void ScannerConn_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(scannerConn.Strength))
{
//MainThread.BeginInvokeOnMainThread(() =>
//{
new HistoricalData();
needlePointer.Value = scannerConn.Strength;
Number.Text = scannerConn.Strength.ToString();
Debug.WriteLine("test1 " + needlePointer.Value);
Debug.WriteLine("test2 " + Number.Text);
//});
}
}
But the guage value doesn't change.
Note I did a similar approach for a list that shows Network names by adding in the code behind the following line:
NetworkListView.ItemsSource = scannerConn.NetworkNames;
The difference is that the names are saved in an ObservableCollection
. And this shows the new names in the listView while the scan is running.
Finally this is the xaml:
<Frame Grid.Row="1">
<Grid>
<gauge:SfRadialGauge x:Name="radialGauge">
<!-- more stuff -->
<gauge:RadialAxis.Pointers>
<gauge:NeedlePointer x:Name="needlePointer" />
</gauge:RadialAxis.Pointers>
<gauge:RadialAxis.Annotations>
<gauge:GaugeAnnotation x:Name="annotation" DirectionUnit="Angle" DirectionValue="90" PositionFactor="0.5">
<gauge:GaugeAnnotation.Content>
<Label x:Name="Number" FontSize="25" FontAttributes="Bold" TextColor="Black"/>
</gauge:GaugeAnnotation.Content>
</gauge:GaugeAnnotation>
<!-- more stuff -->
Update!!!!
this is the console out put of the data I get:
strength: -24
15:24:50:061 existingNetwork: device_1_dummy -24
15:24:50:061 NetworkName: device_1_dummy -24
15:24:50:061 NetworkName: device_1_dummy -24
15:24:50:061 NetworkName: device_1_dummy -25
15:24:52:309 Data received from the scanner: message: datastearm, name: b'device_1_dummy', type: LoRaRAW, lat: None, lon: None, rssi: -25, snr: 6.0, time: (2023, 6, 15, 20, 32, 39, 775777, None)
strength: -25
....and so on
The negative number is the RSSI value I am after.
With the dummy data that I am getting there is only one network name however the RSSI value changes all the time. I tried using on click and on Item selected events. With These I only get one RSSI value and it shows on the gauge.
PLEASE NOT I AM A NOOBIE STILL
答案1
得分: 1
在 SerialPort_DataReceived
方法中,您正在设置 strength
,它是一个私有字段,而不是 Strength
,它是一个公共属性。后者会触发一个 PropertyChanged
事件,而前者不会。
英文:
in SerialPort_DataReceived
you are setting strength
which is a private field, not Strength
which is a public property. The latter fires a PropertyChanged
event, the former does not
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论