Home > Software engineering >  .net Maui Accessing the data item in a CollectionView when a button is clicked
.net Maui Accessing the data item in a CollectionView when a button is clicked

Time:06-09

Man this is like walking through treacle :(

Okay, so I have a class in a folder called models. I have a viewmodel in a folder called ViewModels and a Page that displays a list of Bluetooth connections - don't get excited it's only dummy data :sigh

enter image description here

So Here is the code BluetoothPeripheral.cs

namespace TSDZ2Monitor.Models;

public class BluetoothPeripheral
{
  public string Name    { get; set; }
  public string Id      { get; set; } 
  public bool   Enabled { get; set; }
}
namespace TSDZ2Monitor.ViewModels;

public partial class BluetoothPeripheralsViewModel : ObservableObject
{
  [ObservableProperty]
  public ObservableCollection<BluetoothPeripheral> bluetoothPeripherals = new()
  {
    new BluetoothPeripheral
    {
      Name = "Heart Rate Monitor",
      Id = "12:12:12:12:AB",
      Enabled = true
    },
    new BluetoothPeripheral
    {
      Name = "Speedometer",
      Id = "34:34:34:34:CD",
      Enabled = true
    },
    new BluetoothPeripheral
    {
      Name = "Cadence",
      Id = "56:56:56:56:EF",
      Enabled = true
    },
    new BluetoothPeripheral
    {
      Name = "TSDZ2Monitor Motor",
      Id = "78:78:78:78:GH",
      Enabled = true
    }
  };


  public ICommand DeleteBLEItemCommand => new Command(DeleteBLEItemControl);
  public void DeleteBLEItemControl(object o)
  {
    Console.WriteLine($"delete {o}");
  }
}

and the BluetoothPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TSDZ2Monitor.ViewModels"
             x:Class="TSDZ2Monitor.Pages.BluetoothPage"
             Title="Bluetooth Page">

  <ContentPage.BindingContext>
    <local:BluetoothPeripheralsViewModel />
  </ContentPage.BindingContext>


  <StackLayout>
    <Label Text="Bluetooth LE Connections" />
    <Label Text="{Binding Test}" />

    <CollectionView
      ItemsSource="{Binding BluetoothPeripherals}"
      EmptyView="No data available"
      VerticalOptions="StartAndExpand"
      SelectionMode="Single"
      ItemsLayout="VerticalList"
      HeightRequest="240">
      <CollectionView.ItemTemplate>
        <DataTemplate>
          <Grid
             ColumnDefinitions="*,*,auto">

            <Label Grid.Column="0" 
                   Text="{Binding Name}"
                   FontSize="20"
                   TextColor="Yellow"/>
            <Label Grid.Column="1" 
                   Text="{Binding Id}" 
                   FontSize="20"
                   TextColor="Yellow"/>
            <Button Grid.Column="2" 
                    Text="Del" 
                    WidthRequest="50"
                    HeightRequest="20"
                    Command="{Binding Source={RelativeSource AncestorType={x:Type local:BluetoothPeripheralsViewModel}}, Path=DeleteBLEItemCommand}"
                    CommandParameter="{Binding}"/>

          </Grid>
        </DataTemplate>
      </CollectionView.ItemTemplate>
    </CollectionView>


  </StackLayout>
</ContentPage>

Now the list displays - yay to me after hours of searching.

I click the button on a list item and it calls the DeleteBLEItemCommand which calls the DeleteBLEItemControl - using the ancestor thing! After even more hours.

Now I want to get access to the object (probably so I can delete it from my list or do other things)

Now if I put a breakpoint on the Console.WriteLine and open up an immediate window I can type in o and I get

o
{TSDZ2Monitor.Models.BluetoothPeripheral}
    Enabled: true
    Id: "56:56:56:56:EF"
    Name: "Cadence"

but if I type o.Name in the immediate window

o.Name
Unknown member: Name

Uh???

I admit C# at this level isn't my thing (yet) but it's there so why can't I access it? Please help me, or show me a better way.

btw is there some documentation or tutorial somewhere that really explains what is going on and has some simple working examples (rather than the contrived and overly complex MS examples in the docs)?

Thanks again. G

CodePudding user response:

you are specifying type object. Either cast it to the correct type, or use Command<T> to specify the type

public ICommand DeleteBLEItemCommand => new Command<BluetoothPeripheral>(DeleteBLEItemControl);

public void DeleteBLEItemControl(BluetoothPeripheral o)
{
  Console.WriteLine($"delete {o}");
}

CodePudding user response:

or as was done in a previous post that I asked at net maui app crashes on basic delete from list

So sorry for that. I just hadn't made the link to previous knowledge I should have gained.

  public void DeleteBLEItemControl(object o)
  {
    BluetoothPeripheral bt = o as BluetoothPeripheral;
    Console.WriteLine($"delete {bt.Name}");
  }

in xaml

Command="{Binding Source={RelativeSource AncestorType={x:Type local:BluetoothPeripheralsViewModel}}, Path=DeleteBLEItemCommand}"
CommandParameter="{Binding .}"/>

I think the accepted answer is also cleaner code.

  • Related