[英]Listview is not updating based on ObservableCollection properties
I have a BLE application, which connects to devices and aims to receive a device state dynamically in a listview.I have implemented the Native device class as a model and my viewmodel is seperate in the MainViewModel class. I have a BLE application, which connects to devices and aims to receive a device state dynamically in a listview.I have implemented the Native device class as a model and my viewmodel is seperate in the MainViewModel class. I have implemented INotifyPropretyChanged on both classes but the state of the device is not changing after I connect to it.
我已经在这两个类上实现了 INotifyPropretyChanged,但是设备的 state 在我连接到它后没有改变。 It should be Disconnected, Connecting, Connected,Disconnected and I have a property of Name DeviceState from this BLE plugin that holds this values + I have implemented a INotifyPropretyChanged for it.
它应该是 Disconnected、Connecting、Connected、Disconnected 并且我有一个来自这个 BLE 插件的 Name DeviceState 属性,它保存了这个值 + 我已经为它实现了一个 INotifyPropretyChanged。 I have tried both withoud TwoWay and with it, NotifyCollectionChanged etc. I get the device name and state(Disconnected) successfully but when I connect to it the State should change and it doesnt.
我已经尝试了没有 TwoWay 和 NotifyCollectionChanged 等。我成功地获得了设备名称和状态(断开连接)但是当我连接到它时 State 应该改变并且它没有改变。 It successfully connects and I have tried it on another app without MVVM approach and it gets the states after connecting, but i have to iterate through them in a loop and add them to a separate collection, which is not really efficient.
它成功连接,我在另一个没有 MVVM 方法的应用程序上尝试过它,它在连接后获取状态,但我必须循环遍历它们并将它们添加到单独的集合中,这不是很有效。 Any help would be appriciated, thank you in advance!
任何帮助将不胜感激,在此先感谢您!
class NativeDevice : INotifyPropertyChanged
{
private string deviceNameValue = String.Empty;
public event PropertyChangedEventHandler PropertyChanged;
private DeviceState states;
public NativeDevice(string name, DeviceState stated)
{
deviceNameValue = name;
states = stated;
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public string Name
{
get
{
return this.deviceNameValue;
}
set
{
if (value != this.deviceNameValue)
{
this.deviceNameValue = value;
OnPropertyChanged();
}
}
}
public DeviceState States
{
get
{
return states;
}
set
{
this.states = value;
OnPropertyChanged();
}
}
}
class MainViewModel : INotifyPropertyChanged
{
public ObservableCollection<IDevice> BluetoothDevices { get; set; }
public ObservableCollection<NativeDevice> devicesFound;
public ObservableCollection<NativeDevice> DevicesFound { get { return devicesFound; }
set { devicesFound = value; OnPropertyChanged(); } }
public event PropertyChangedEventHandler PropertyChanged;
private readonly IAdapter _bluetoothAdapter;
public AsyncCommand ScanForDevices { get; }
public AsyncCommand ConnectToDevices { get; }
CancellationTokenSource source = new CancellationTokenSource();
public MainViewModel()
{
ScanForDevices = new AsyncCommand(PerformScanAsync);
DevicesFound = new ObservableCollection<NativeDevice>();
BluetoothDevices = new ObservableCollection<IDevice>();
_bluetoothAdapter = CrossBluetoothLE.Current.Adapter;
_bluetoothAdapter.DeviceDiscovered += (s, a) =>
{
BluetoothDevices.Add(a.Device);
};
ConnectToDevices = new AsyncCommand(ConnectAsync);
CancellationToken token = source.Token;
devicesFound = new ObservableCollection<NativeDevice>();
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
async Task PerformScan{
await _bluetoothAdapter.StartScanningForDevicesAsync();
foreach (var item in BluetoothDevices)
{
if (item.Name == "GP")
{
DevicesFound.Add(new NativeDevice(item.Name, item.State));
}
}
await _bluetoothAdapter.StopScanningForDevicesAsync();
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:bleappmodelview="clr-namespace:BleAppModelView.ViewModels" xmlns:bleappmodelview1="clr-namespace:BleAppModelView.Model" x:DataType="bleappmodelview:MainViewModel"
x:Class="BleAppModelView.MainPage">
<ContentPage.BindingContext>
<bleappmodelview:MainViewModel/>
</ContentPage.BindingContext>
<StackLayout>
<Button x:DataType="bleappmodelview:MainViewModel"
Text="Scan"
Command="{Binding ScanForDevices}"
Margin="10" />
<ListView ItemsSource="{Binding DevicesFound}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label x:DataType="bleappmodelview1:NativeDevice" Text="{Binding Name, Mode=TwoWay}"/>
<Label x:DataType="bleappmodelview1:NativeDevice" Text="{Binding States, Mode=TwoWay}" TextColor="Red"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button x:DataType="bleappmodelview:MainViewModel"
Text="Connect"
Command="{Binding ConnectToDevices}"
Margin="10"/>
</StackLayout>
</ContentPage>
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainViewModel();
}
}
namespace Plugin.BLE.Abstractions
{
public enum DeviceState
{
Disconnected = 0,
Connecting = 1,
Connected = 2,
Limited = 3
}
}
async Task ConnectAsync()
{
foreach (var device in BluetoothDevices)
{
if (device.Name == "GP")
{
var parameters = new ConnectParameters(forceBleTransport: true);
await _bluetoothAdapter.ConnectToDeviceAsync(device, parameters, source.Token);
}
}
}
you need to update the object your UI is bound to when the connection state changes当连接 state 更改时,您需要更新您的 UI 绑定的 object
there are a LOT of different ways to approach this, one simple one would be有很多不同的方法可以解决这个问题,一种简单的方法是
async Task ConnectAsync()
{
foreach (var device in BluetoothDevices)
{
if (device.Name == "GP")
{
var parameters = new ConnectParameters(forceBleTransport: true);
await _bluetoothAdapter.ConnectToDeviceAsync(device, parameters, source.Token);
// find the matching device in DevicesFound
var d = DevicesFound.Where(x => x.Name == device.Name).FirstOrDefault();
d.States = DeviceState.Connected;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.