Home > Back-end >  How to show object when checkbox is checked using Xamarin Forms
How to show object when checkbox is checked using Xamarin Forms

Time:10-04

How to show an object when user selected the checkbox in grid? The data is in Collection view which put in Grid. And the Process button is in below grid as well. Can it be done even I'm using MVVM?

For example they selected any:

enter image description here

The Process button will show and hide when no selected item. Below is the XAML

    <StackLayout >
    <!--<SearchBar Placeholder="Search..."/>-->
    <RefreshView   x:DataType="local:ShpAgentMainPageViewModel"  Command="{Binding LoadReleaseDocumentsSA}" 
                       IsRefreshing="{Binding IsRefreshing ,Mode=OneWay}" RefreshColor="#FFFF7F50">
        <CollectionView   x:Name="DeliveredList" 
                    ItemsSource="{Binding DeliveredDocuments}"
                    SelectionMode="None" >
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout   Padding="3" x:DataType="model:Deliver"> 
                        <Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                            ...
                        </Grid> 
                    </StackLayout> 
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </RefreshView>
    <Grid x:Name="BelowMenu">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button 
            CornerRadius="5"
            Grid.Row="0" 
            Text="PROCESS"  
            FontAttributes="Bold" 
            BackgroundColor="#FF7F50" 
            TextColor="White"  
            WidthRequest="100" 
            HeightRequest="70" 
            Margin="20,0,20,22" 
            HorizontalOptions="End" 
            VerticalOptions="End" 
            Command="{Binding TMPendingDetailsPageShpAgent}"        
            />   
    </Grid>
</StackLayout>

For my ViewModel:

public class ShpAgentMainPageViewModel : BaseViewModel
{
    public Command<Deliver> TMPendingDetailsPageShpAgent { get; set; }
    public ShpAgentMainPageViewModel()
    {
        try
        {
             
            TMPendingDetailsPageShpAgent = new Command<Deliver>(OnTMPendingTransferPageShpAgentTap);
 
        }
        catch(Exception ex)
        {
            Debug.WriteLine(ex);

            Debug.WriteLine(ex.ToString()); 
        }
    }

    async void OnTMPendingTransferPageShpAgentTap(Deliver Book)
    {
        IEnumerable<String> selectedData = DeliveredDocuments.Where(d => d.IsSelected).Select(d => d.TMNo).ToArray();
        if (selectedData.Count() == 0)
            return;

        string tmNo = string.Join("|", selectedData);

        try
        {
            ...
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.ToString()); 
        }
  
    }   
}

CodePudding user response:

Sure it can be done.

In Xamarin MVVM you should use bindings for things like these. You can use these in a few variations:

  1. Bind directly to another element (or its member) in the view
  2. Bind to a value in the view model (typical usage)
  3. Bind to the result of a converter (to change the type of a binded value)
  4. Markup extensions (can be used to convert the type of value defined in xaml)

For your use case you have two options:

  • a combination of (1) and (3):

    Set SelectionMode="Multiple" to use the built in selection mechanics of the CollectionView. CollectionView has a property SelectedItems, see: doc. Bind the IsVisible property of the process button to the CollectionView's SelectedItems. Linking to the right object is the difficult part. Use the Source property on the binding, to make sure it looks for the object in the right place (view, and not view model). Pay attention to the debug messages at runtime, these will tell you when a binding is failing.

    Then do the type conversion with a IsNotEmptyConverter. This takes your List, does something like return list.Count > 0.

  • a combination of (2) and (3): Ditch the CollectionView if you're not using the built-in mechanics for selection. StackLayout with ItemSource is the most simple option. Bind the IsVisible property of the process button to your viewmodel's DeliveredDocuments. Then write a AnyDocumentIsSelected converter that takes a List<DeliveredDocuments> and returns true if any of them have a IsSelected that is true.

CodePudding user response:

Since we couldn't see other detailed code of your project(e.g. Deliver), but you can refer to the following code which achieving the similar function.

MeetAWalkerViewModel.cs

    public class MeetAWalkerViewModel: INotifyPropertyChanged
{
    public ObservableCollection<PetProfile> source;
    //public ObservableCollection<PetProfile> PetInfo { get; private set; }
    public ObservableCollection<PetProfile> EmptyPetInfo
    {
        get => source;
        private set
        {
            if (value != source)
            {
                source = value;
                OnPropertyChanged(nameof(EmptyPetInfo));
            }
        }
    }

    int _count;
    public int Count
    {
        set
        {
            if (_count != value)
            {
                _count = value;
                OnPropertyChanged(nameof(Count));

                Sel = "Amount of selected pets is : "   Convert.ToString(_count);
            }
        }
        get
        {
            return _count;
        }
    }

    public void updateCount(int count) { 
    
    }

    String sel;
    public String Sel
    {
        set
        {
            if (sel != value)
            {
                sel = value;
                OnPropertyChanged(nameof(Sel));
            }
        }
        get
        {
            return sel;
        }
    }

    public MeetAWalkerViewModel()
    {
        EmptyPetInfo = new ObservableCollection<PetProfile>();
        EmptyPetInfo.Add(new PetProfile { PetName = "Pet1", IsSelected= false,ImageUrl= "cherry.png" });
        EmptyPetInfo.Add(new PetProfile { PetName = "Pet2", IsSelected = false, ImageUrl = "watermelon.png" });
        EmptyPetInfo.Add(new PetProfile { PetName = "Pet3", IsSelected = false, ImageUrl = "cherry.png" });
        EmptyPetInfo.Add(new PetProfile { PetName = "Pet4", IsSelected = false, ImageUrl = "watermelon.png" });
        EmptyPetInfo.Add(new PetProfile { PetName = "Pet5", IsSelected = false, ImageUrl = "cherry.png" });
        EmptyPetInfo.Add(new PetProfile { PetName = "Pet6", IsSelected = false, ImageUrl = "watermelon.png" });

        foreach (PetProfile petProfile in EmptyPetInfo) {
            if (petProfile.IsSelected)
            {
                Count  ;
            }

        }
        Sel = "Amount of selected pets is : "   Convert.ToString(Count);
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

MainPage.xaml

<StackLayout HorizontalOptions="Center"  Padding="10" >
    <Label   x:Name="countSelectedItemsLabel" Text="{Binding Sel}" FontSize="20" />

    <CollectionView  x:Name="petCollectionView"  ItemsSource="{Binding EmptyPetInfo}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Grid Padding="10" RowDefinitions="80" ColumnDefinitions="120,60,60">
                    <Image Grid.Column="0"
                            Grid.Row="0"
                            x:Name="PetImage"
                            Source="{Binding ImageUrl}"/>
                    <Label Grid.Column="1"
                            Grid.Row="0"
                            Text="{Binding PetName}"
                            FontAttributes="Bold"
                            x:Name="labelpetname" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/>
                    <CheckBox  Grid.Row="0" Grid.Column="2" HorizontalOptions="End" IsChecked="{Binding IsSelected, Mode=TwoWay}" CheckedChanged="CheckBox_CheckedChanged" BindingContext="{Binding .}"/>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</StackLayout>

MainPage.xaml.cs

public partial class MainPage : ContentPage
{

    MeetAWalkerViewModel viewModel;

    int selectedCount = 0;

    public MainPage()
    {
        InitializeComponent();

        viewModel = new MeetAWalkerViewModel();
        BindingContext = viewModel;
    }

    private void CheckBox_CheckedChanged(object sender, CheckedChangedEventArgs e)
    {
        PetProfile model = (PetProfile)((CheckBox)sender).BindingContext;

        if (model.IsSelected)
        {
            selectedCount  ;
        }
        else
        {
            selectedCount--;
        }

        viewModel.Count = selectedCount;

    }
}

PetProfile.cs

 public class PetProfile
{
    public string PetName { get; set; }

    public string ImageUrl { get; set; }

    public bool IsSelected { get; set; }
}

For more information, you can check thread: Count selected checkboxes in collectionview xamarin.

  • Related