Table of Contents

Class NearbyDeviceCollection

Namespace
Plugin.Maui.NearbyConnectivity
Assembly
Plugin.Maui.NearbyConnectivity.dll

The device set as a bindable, live collection of NearbyDevice, kept in sync by handling DeviceChanged and applying each change on a dispatcher's thread.

public sealed class NearbyDeviceCollection : IReadOnlyList<NearbyDevice>, IReadOnlyCollection<NearbyDevice>, IEnumerable<NearbyDevice>, IEnumerable, INotifyCollectionChanged, INotifyPropertyChanged, IDisposable
Inheritance
NearbyDeviceCollection
Implements
Inherited Members

Examples

// Constructed on the UI thread, so the dispatcher is found rather than passed.
public NearbyDeviceCollection Devices { get; } = new(nearby);

Remarks

Optional. INearbyConnectivity itself has no thread affinity. It hands out immutable snapshots and raises its events on a thread-pool thread. This type exists only for callers who want a collection they can bind to XAML, and it is the one place in the plugin that assumes a UI thread exists.

Construct one per view that needs it, and dispose it when the view goes away. Disposal unsubscribes from the session, which otherwise keeps this collection alive for as long as it lives. Constructed on the dispatcher's thread, it already holds every device the session knows when the constructor returns, so a bound list renders full rather than filling a frame later.

Read this collection only on the dispatcher's thread. Devices are added and removed on that thread, so Count, the indexer, and GetEnumerator() can observe a torn collection from anywhere else. This is the same rule as any ObservableCollection<T> bound to a user interface.

The collection is read-only to its callers. It mirrors what the session reports and cannot be added to or removed from directly. It raises CollectionChanged, so it binds straight to an ItemsSource.

A device is a value, so a change is a replacement. Each row is an immutable snapshot, and a changed device is assigned over the old one, raising Replace so a bound row refreshes in place. When rows need state a snapshot cannot carry, such as a command or a selection, project them yourself from DeviceChanged into a collection you own.

A failure is reported, not thrown. If the filter throws, the collection keeps the devices it has, stops updating, and sets Exception and IsFaulted so a page can say so. The exception is also logged through the logger the plugin's session was registered with; an INearbyConnectivity of your own, such as a decorator, is not logged. Nothing is thrown on the dispatcher's thread, so a broken filter never takes the application down.

Constructors

NearbyDeviceCollection(INearbyConnectivity, IDispatcher?, Func<NearbyDevice, bool>?)

Initializes a new instance of the NearbyDeviceCollection class and begins watching the session's device set.

public NearbyDeviceCollection(INearbyConnectivity nearby, IDispatcher? dispatcher = null, Func<NearbyDevice, bool>? filter = null)

Parameters

nearby INearbyConnectivity

The session to watch.

dispatcher IDispatcher

Where mutations and change events run. null uses the current thread's dispatcher, so a view model constructed on the UI thread can omit it.

filter Func<NearbyDevice, bool>

Which devices to include, or null for all of them. Re-evaluated on every change, so a device joins and leaves the collection as it starts and stops matching.

Exceptions

ArgumentNullException

nearby is null.

InvalidOperationException

dispatcher is null and the current thread has none.

Properties

Count

Gets the number of devices currently shown.

public int Count { get; }

Property Value

int

Remarks

Read only on the dispatcher's thread.

Exception

Gets what stopped this collection following the session, or null while it still does.

public Exception? Exception { get; }

Property Value

Exception

The exception the filter threw, as it was raised.

Remarks

Once set, the collection keeps the devices it had and never changes again. Construct a new one to follow the session afresh. Raises PropertyChanged, as does IsFaulted.

IsFaulted

Gets whether Exception is set: the collection has stopped following the session.

public bool IsFaulted { get; }

Property Value

bool

this[int]

Gets the device at the specified index.

public NearbyDevice this[int index] { get; }

Parameters

index int

The zero-based index of the device to get.

Property Value

NearbyDevice

The device at index.

Remarks

Read only on the dispatcher's thread. Indexing from another thread can throw even for an index that was valid when it was chosen, because a removal can land in between.

Exceptions

ArgumentOutOfRangeException

index is outside the bounds of the collection.

Methods

Dispose()

Stops following the session and unsubscribes from DeviceChanged.

public void Dispose()

Remarks

Idempotent. Calling this more than once performs no additional work.

GetEnumerator()

Returns an enumerator that iterates through the devices currently shown.

public IEnumerator<NearbyDevice> GetEnumerator()

Returns

IEnumerator<NearbyDevice>

An enumerator over the collection.

Remarks

Enumerate only on the dispatcher's thread.

Events

CollectionChanged

Occurs when devices are added, replaced, or removed.

public event NotifyCollectionChangedEventHandler? CollectionChanged

Event Type

NotifyCollectionChangedEventHandler

Remarks

Raised from inside the dispatcher, so every handler, including a XAML binding, runs on the bound thread.

PropertyChanged

Raised when Count or the indexer changes.

public event PropertyChangedEventHandler? PropertyChanged

Event Type

PropertyChangedEventHandler

Remarks

Forwarded from the inner ObservableCollection<T>, so that {Binding Devices.Count} updates as devices come and go. Also raised for Exception and IsFaulted.

See Also