0

I have an application that draws use of Xabre.ble plugin.

When the application scans for devices, once a device is discovered the application appends it to an ObservableCollection which derives from an interface.

I have made a Data template in Xaml that i wish to populate, but for some reason i can't seem to get the BindingContext right.

Basically, what I want to achieve, is to add device objects to my ObservableCollection IDevice, and fetch just the name of the individual devices in the bindingcontext for the user to see in the listview

Xaml:

<ListView x:Name="deviceList">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/> 
                        <ColumnDefinition Width="Auto"/>
                   </Grid.ColumnDefinitions>
                   <local:IconView Grid.Row="0" Grid.Column="0" Source="BLE.png" Foreground="#3b5998" WidthRequest="30" HeightRequest="30"/>
                   <Label Grid.Row="1" Text="{Binding DeviceName}" TextColor="Teal"/>
                </Grid>
            </ViewCell>
        </DataTemplate> 
    </ListView.ItemTemplate>
</ListView>

Cs:

public ObservableCollection<IDevice> Devices { get; set; }
IAdapter adapter = CrossBluetoothLE.Current.Adapter;
public ObservableCollection<string> DeviceName { get; set; }

public MainPage()
{
    //Instantiate observable collection
    Devices = new ObservableCollection<IDevice>();
    DeviceName = new ObservableCollection<string>();

    //Appending peripherals to list
    BindingContext = DeviceName;
    deviceList.ItemsSource = BindingContext;
    Content = deviceList;
    Refreshcmd();
}
public void Refreshcmd()
{
//DeviceDiscovered is an event, when it discovers a device, we fire the eventhandler
    adapter.DeviceDiscovered += (s, a) =>
    {
        if (a.Device.Name != null)
        {
            Devices.Add(a.Device);               
            DeviceName.Add(a.Device.Name);
        }
    };
    adapter.StartScanningForDevicesAsync();
}

As you can see, I have tried to make an object which contains a string with just the name of the IDevice. However, it doesn't append to my databinding DeviceName.

Furthermore, I don't really like this solution, as I would much rather be able to access the Devices.Name from the interface, but that is not allowed apparently. - the reason why I would much rather like that solution is that the user eventually will have to connect to a device from the list, meaning that it is much easier to have one object for all the "behind the scenes" details.

4
  • Its a different control but your problem is similar to this - stackoverflow.com/questions/5409259/… Commented Sep 27, 2018 at 12:10
  • Had another look at what you are doing - try to change <Label Grid.Row="1" Text="{Binding DeviceName}" TextColor="Teal"/> to this <Label Grid.Row="1" Text="{Binding}" TextColor="Teal"/> Commented Sep 27, 2018 at 12:12
  • Why are you messing with the BindingContext ? Why can't the MainPage be the BindingContext for your XAML ? Commented Sep 27, 2018 at 12:14
  • Is there a reason why you try to use two lists? Devices and DeviceName Commented Sep 27, 2018 at 12:16

1 Answer 1

2

You should refactor your code, to a MVVM approach.

namespace YourNameSpace.ViewModels
{
    public class YourViewModel
    {

        private ObservableCollection<IDevice> devices;
        public ObservableCollection<IDevice> Devices
        {
            get { return devices; }
            set
            {
                devices = value;
            }
        }
        public YourViewModel()
        {
            Devices = new ObservableCollection<IDevice>();
        }
    }
}

In your Page.xaml.cs

public partial class YourPage : ContentPage
    {
        public YourPage()
        {
            InitializeComponent();
            BindingContext = new YourViewModel();
        }
    }

    public void Refreshcmd()
{
//DeviceDiscovered is an event, when it discovers a device, we fire the eventhandler
    adapter.DeviceDiscovered += (s, a) =>
    {
        if (a.Device.Name != null)
        {
            (YourViewModel)Devices.Add(a.Device);               
            //DeviceName.Add(a.Device.Name);
        }
    };
    adapter.StartScanningForDevicesAsync();
}

Then in Page.xaml

 <ListView ItemsSource="{Binding Devices}"
              CachingStrategy="RecycleElement">
Sign up to request clarification or add additional context in comments.

6 Comments

It works, but if i for example want to show the IDevice.Id, would I then just go {Binding Id} ? cause it doesn't show anything in that case.
Yes, in your ViewCell, you just need to Bind to the IDevice Property you desire.
In that case, I just wrote {Binding Id} but it doesn't show anything. I guess it doesn't affect anything that it is Int. It still should show right?
Yes, it should show even though its int. Have you tried to Bind to other properties? Are they showing correctly?
Hmm, i just tried printing the Rssi state, and that actually seems to work just fine!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.