简体   繁体   English

Listview 不会根据 ObservableCollection 属性进行更新

[英]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.

相关问题 ListBox ObservableCollection属性未更新 - ListBox ObservableCollection Properties Not Updating 更换ObservableCollection时ListView不更新 - ListView not updating when ObservableCollection is replaced 更改ObservableCollection后ListView不更新 - ListView not updating after ObservableCollection is changed 将对象实例的属性从ObservableCollection绑定到ListView - Binding properties of object instances from ObservableCollection to ListView 绑定的ObservableCollection更改时,ListView不更新 - ListView not updating when the bound ObservableCollection changes "ListView 未更新 itemsource ObservableCollection 项目属性更改" - ListView not updating on the itemsource ObservableCollection Item Property change 如何将ListView的一个ObservableCollection的属性绑定到另一个ListView的SelectedItem的属性? - How to bind properties of one ObservableCollection of ListView to properties of SelectedItem of another ListView? 使用INotifyPropertyChanged更新ObservableCollection项属性 - Updating ObservableCollection Item properties using INotifyPropertyChanged 当更新绑定到Listview的ObservableCollection中的Item时,指定的强制转换无效 - Specified cast not Valid when updating Item in ObservableCollection bound to Listview 更新ObservableCollection无法正确更新Xamarin Forms中的ListView - Updating ObservableCollection does not properly update ListView in Xamarin Forms
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM