Reputation: 1890
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.
Upvotes: 0
Views: 829
Reputation: 7199
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">
Upvotes: 2