Search code examples
c#xamlmaui

Accessing current item in Collection View with parent command


I have an a MAUI front end that connect to a button successfully from the VM with

Command="{Binding BindingContext.ImageCreateCommand, Source={x:Reference PageName}}

The full MAUI commands are inside a collection view such as

<CollectionView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="9" VerticalOptions="FillAndExpand" 
                    ItemsSource="{Binding class}">
                    <CollectionView.ItemTemplate>
                        <DataTemplate x:DataType="models:class">
...
    <Button Text="Add" Grid.Column="0" Command="{Binding BindingContext.ImageCreateCommand, Source={x:Reference WorkNotification}}" CommandParameter="{Binding id}"></Button>
    <Label TextColor="{DynamicResource SecondaryTextColor}" Grid.Column="1" Text="{Binding id}" Style="{DynamicResource ContentLabel}"/>
    <Label TextColor="{DynamicResource SecondaryTextColor}" Grid.Column="2" Text="{Binding txt}" Style="{DynamicResource ContentLabel}"/>
..

I want to use the CommandParameter="{Binding id} in the collection view so I can do something with the id but I am not successful when I put it in the button CommandParameter

My View Model is such:

public ObservableRangeCollection<class> class { get; } = new();

public viewmodel(string funcLoc)
    {
        ImageCreateCommand = new Command(async () =>
        {
           Console.WriteLine(id);
        }
    };

The document says You can set the CommandParameter property to arbitrary data to distinguish between multiple buttons if they are all bound to the same ICommand property in the viewmodel which is done because the CollectionView sees the id and displays it.

How do I use an Item in the collection view as a parameter in this command.


Solution

  • It's difficult to deduce what's wrong from the current state of the question, but I'll provide a generic answer, anyway.

    If you have a collection of items and you would like to use them or any of their properties as a CommandParameter, then you can do that as follows.

    In the ViewModel you have a collection, let's say an ObservableCollection<MyItem> where MyItem is defined as follows:

    public class MyItem
    {
        public int Index { get; set; }
        public string Id { get; set; }
    }
    

    Your ViewModel, let's call it MyViewModel also has a Command, let's call that MyCommand and it takes a string as a parameter, then it will look something like this:

    public class MyViewModel : ObservableObject
    {
        private ObservableCollection<MyItem> items;
        public ObservableCollection<MyItem> Items
        {
            get => items;
            set => SetProperty(ref items, value);
        }
    
        private IRelayCommand<string> myCommand;
        public IRelayCommand<string> MyCommand => myCommand ??= new RelayCommand<string>(MyMethod);
    
        private void MyMethod(string id)
        {
            Console.WriteLine(id);
        }
    }
    

    In your XAML, you can then set up a <CollectionView> where you can reference the MyCommand command and pass in the Id property as a parameter.

    This requires that you have set an instance of MyViewModel as the BindingContext, e.g. in the code-behind of your View or Page:

    public partial class MyPage : ContentPage
    {
        public MyPage()
        {
            InitializeComponent();
            BindingContext = new MyViewModel();
        }
    }
    

    Then, in the XAML of MyPage, you can setup the <CollectionView> and Command bindings using a Relative Binding to the ViewModel:

    <CollectionView
        ItemsSource="{Binding Items}">
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="models:MyItem">
                <Button
                    Text="{Binding Id}"
                    Command="{Binding MyCommand, Source={RelativeSource AncestorType={x:Type viewmodels:MyViewModel}}"
                    CommandParameter="{Binding Id}" />
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>