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:
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:
- Bind directly to another element (or its member) in the view
- Bind to a value in the view model (typical usage)
- Bind to the result of a converter (to change the type of a binded value)
- 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 theCollectionView
.CollectionView
has a propertySelectedItems
, see: doc. Bind theIsVisible
property of the process button to theCollectionView
'sSelectedItems
. Linking to the right object is the difficult part. Use theSource
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 yourList
, does something likereturn list.Count > 0
.a combination of (2) and (3): Ditch the
CollectionView
if you're not using the built-in mechanics for selection.StackLayout
withItemSource
is the most simple option. Bind theIsVisible
property of the process button to your viewmodel'sDeliveredDocuments
. Then write aAnyDocumentIsSelected
converter that takes aList<DeliveredDocuments>
and returns true if any of them have aIsSelected
that istrue
.
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.