Yassine El mesbahy
Yassine El mesbahy

Reputation: 25

How to Capture Selected CheckBox Items and Update a List with MVVM in .Net maui

This is my first time working on a MAUI app and struggling with a scenario where I need to capture the selected CheckBox items from a collection and store their relevant Section objects into a list when I click a button (I've seen some people add to the model boolean property to see if the item is selected or not but i didn't do that) .

I have a CollectionView that displays a list of Sections:

<CollectionView ItemsSource="{Binding Sections}"
                                Grid.Row="1">
                                <CollectionView.ItemTemplate>
                                    <DataTemplate>
                                        <HorizontalStackLayout>
                                        <!-- I don't know what to add to the check box to handle the selecting event -->
                                            <CheckBox Color="#0B4C90"/>
                                            <Label Text="{Binding SectionName}"
                                       FontSize="20"
                                       FontAttributes="Bold"
                                       TextColor="#0B4C90"/>
                                        </HorizontalStackLayout>
                                    </DataTemplate>
                                </CollectionView.ItemTemplate>
                            </CollectionView>
                        </Border>
<Buton Text="Get Sections"/>

Here is the Section Model : (i called it 'Rayon' because it wouldn't let me name it Section)

public class Rayon
    {
        [Key]
        public int Id { get; set; }
        public string SectionName { get; set; } = null!;
        public ICollection<SectionSupplier> SectionSuppliers { get; set; } = null!;
        public ICollection<Product> Products { get; set; } = null!;
    }`
And here is my view model : 
`public partial class CreateSupplierPageViewModel : ObservableObject
{

/* This is the list that i want to Add or remove Sections from whenever i check or uncheck one of the checkboxs */ 
    private ObservableCollection<Rayon> _selectedSections;
        public ObservableCollection<Rayon> SelectedSections
        {
            get => _selectedSections;
            set
            {
                _selectedSections = value;
            }
        }

        public ObservableCollection<Rayon> Sections { get; set; } = new ObservableCollection<Rayon>();

public async Task GetSectionsList()
        {
            var sectionList = new List<Rayon>();

            var sectionUrl = "https://localhost:7282/api/Sections/GetSections";

            using (var client = new HttpClient())
            {
                var Apiresponse = await client.GetAsync(sectionUrl);

                if (Apiresponse.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    var content = await Apiresponse.Content.ReadAsStringAsync();
                    sectionList = JsonConvert.DeserializeObject<List<Rayon>>(content);
                }

            }

            if (sectionList?.Count > 0)
            {
                foreach (var section in sectionList)
                {
                    Sections.Add(section);
                }
            }
        }

/*This method is used simply because i couldn't call GetSectionsList directly in the constructor to avoid deadlocks */

public static async Task<CreateSupplierPageViewModel> Create()
        {
            var it = new CreateSupplierPageViewModel();
            await it.Initialize();
            return it;
        }

        private async Task Initialize()
        {
            await GetSectionsList();
        }
        public CreateSupplierPageViewModel()
        {
            SelectedSections = new ObservableCollection<Rayon>();
        }
}

I'm looking for guidance on how to capture the selected Sections when the button is clicked. Any help or code samples would be greatly appreciated. Thank you!

I tried Looking in the net for a solution but whatever i find just confuses me because i don't know what or where should i place the code that i find in the solutions . i tried also using chat gpt but it whatever solution it provides it doesn,t work

Upvotes: 1

Views: 1880

Answers (1)

Jessie Zhang -MSFT
Jessie Zhang -MSFT

Reputation: 13879

Yes, you can add a bool field to the model (Rayon.cs) of list Sections and bind it to the CheckBox. This is also the method we often use.

Of course, if you really want to trigger the selecting event, you can use EventToCommandBehavior to achieve this.

I created a demo and tried to achieve this function with two methods above.

You can refer to the following code:

MainPage.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:viewdels="clr-namespace:MauiCheckListviewApp.ViewModes"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:Class="MauiCheckListviewApp.MainPage">

    <ContentPage.BindingContext>
        <viewdels:MyViewModel></viewdels:MyViewModel>
    </ContentPage.BindingContext>

    <VerticalStackLayout>
        <CollectionView ItemsSource="{Binding Sections}" x:Name="myCollectionView"
                                Grid.Row="1">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <HorizontalStackLayout>
                      
                        <CheckBox Color="#0B4C90" IsChecked="{Binding IsChecked}">
                            <CheckBox.Behaviors>
                                <toolkit:EventToCommandBehavior
                                    Command="{Binding BindingContext.UpdateThisItemCommand, Source={x:Reference myCollectionView}}"
                                    CommandParameter="{Binding .}"
                                    EventName="CheckedChanged" />
                            </CheckBox.Behaviors>

                        </CheckBox>
                        <Label Text="{Binding SectionName}"
                                       FontSize="20"
                                       FontAttributes="Bold"
                                       TextColor="#0B4C90"/>
                    </HorizontalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

        <Button Text="Get Sections" Command="{Binding GetResultCommand}"/>
    </VerticalStackLayout>

</ContentPage>

MyViewModel.cs

public class MyViewModel 
{
    public ObservableCollection<Rayon> Sections { get; set; } = new ObservableCollection<Rayon>();

    public ICommand GetResultCommand { get; set; }
    public ICommand UpdateThisItemCommand { get; set; }


    public MyViewModel() {
        Sections.Add(new Rayon { SectionName= "section_1"});
        Sections.Add(new Rayon { SectionName= "section_2"});
        Sections.Add(new Rayon { SectionName= "section_3"});


        GetResultCommand = new Command(getResult);

        UpdateThisItemCommand = new Command<Rayon>(checkboxcommand);

    }

    private void checkboxcommand(Rayon obj)
    {
        if (obj != null)
        {
            if (obj.IsChecked)
            {
                // you also need to add some other logic codes here

               
            }
           
        }
    }

    private void getResult()
    {
        foreach (var section in Sections)
        {
            if (section.IsChecked) { 
                System.Diagnostics.Debug.WriteLine(section.SectionName);
            }
        }
    }
}

Rayon.cs

public class Rayon: INotifyPropertyChanged 
{
    public string SectionName { get; set; }

    private bool _isChecked;
    public bool IsChecked
    {
        set { SetProperty(ref _isChecked, value); }
        get { return _isChecked; }
    }

    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

Note:

Here, we need to install nuget CommunityToolkit.Maui and initialize the package correctly.

For more information, you can check document: Get started.

Upvotes: 1

Related Questions