Reputation: 31333
The code below shows a simple example of a CollectionView. I am not receiving the event for the SelectionChangedCommand. Can someone see what I am doing wrong?
btw, the complete source for this can be found on GitHub here.
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ControlDemo"
x:Class="ControlDemo.MainPage">
<StackLayout>
<CollectionView SelectionMode ="Single"
ItemsSource="{Binding Tags}"
SelectionChangedCommand="{Binding SelectedTagChanged}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding .}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
MainPageModel.cs
public class MainPageModel : FreshBasePageModel
{
public override void Init(object initData)
{
Tags = new List<string>() { "A", "B", "C" };
base.Init(initData);
}
public List<string> Tags { get; set; }
public Command SelectedTagChanged
{
get
{
return new Command(() =>
{
});
}
}
}
Upvotes: 9
Views: 13808
Reputation: 138
I had the same issue, and the SelectionChangedCommand firing only if my Command is setted as object, like said Fabricio P.
XAML
<CollectionView
x:Name="ListaGiocatoriCollectionView"
Grid.Row="3"
Grid.ColumnSpan="2"
Grid.RowSpan="4"
SelectionMode="Multiple"
ItemsSource="{Binding ListaGiocatori}"
SelectionChangedCommand="{Binding PopolaListaGiocatoriScelti}"
SelectionChangedCommandParameter="{Binding .,Source={x:Reference ListaGiocatoriCollectionView}}">
Code
public ICommand PopolaListaGiocatoriScelti => new Command<object>(async (user) =>
{
CollectionView cw = (CollectionView)user;
IList<object> x = cw.SelectedItems;
ListaGiocatoriScelti = new ObservableCollection<User>();
foreach (object item in x)
{
ListaGiocatoriScelti.Add((User)item);
}
});
Upvotes: 0
Reputation: 41
I improved Fabricio P. answer in this way:
So your xaml part will be something like this:
<CollectionView
ItemsSource="{Binding Objects}"
SelectionMode="Single"
SelectionChangedCommand="{Binding SelectObjectCommand}"
SelectionChangedCommandParameter="{Binding SelectedItem, Source={RelativeSource Self}}">
And in your view model:
public ICommand SelectObjectCommand => new Command<string>(i => { Debug.WriteLine("Selected: " + i); });
public IEnumerable<string> Objects { get; set; }
Upvotes: 4
Reputation: 1408
if you are using the Model for it you can use the following method
My C# Model View Class
public class MainView : INotifyPropertyChanged
{
public ICommand SelectionChangedCommands => new Command<GroupableItemsView>((GroupableItemsView query) =>
{
GO_Account test = query.SelectedItem as GO_Account;
});
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
And this is my XAML
<CollectionView x:Name="myAccounts"
SelectionMode="Single"
ItemsSource="{Binding Products}"
SelectionChangedCommand="{Binding SelectionChangedCommands}"
SelectionChangedCommandParameter="{Binding Source={x:Reference myAccountsModel}}">
</CollectionView>
Upvotes: 0
Reputation: 141
Couple of things that worked at my side (additionally to the SelectionMode = Single
):
Make sure your Command' signature is <object>
at your PageModel and do any cast according to your needs (specially if your collection becomes more complex).
Also at your XAML you want to give your CollectionView a name and use the SelectedItem property.
SelectionChangedCommandParameter="{Binding SelectedItem, Source={x:Reference cvTagsCollectionView}}"
Upvotes: 14
Reputation: 15816
I use your code and created a demo on my side, I add the widthRequest
and HeightRequest
to make the collectionView work:
<CollectionView
HeightRequest="170"
WidthRequest="200"
SelectionMode="Single"
SelectionChangedCommand="{Binding SelectedTagChangedCommand}"
ItemsSource="{Binding Tags}"
>
The SelectionChangedCommand
did triggered after I click different items in the CollectionView.
I uploaded a sample here and you can check it: collectionView-selectItemChanged-xamarin.forms
Upvotes: 6
Reputation: 7199
If you want to use your ViewModel, then you should use the Binding for the SelectedItem:
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionMode="Single"
SelectedItem="{Binding SelectedMonkey, Mode=TwoWay}">
...
</CollectionView>
and, in your ViewModel:
Monkey selectedMonkey;
public Monkey SelectedMonkey
{
get
{
return selectedMonkey;
}
set
{
if (selectedMonkey != value)
{
selectedMonkey = value;
}
}
}
So everytime you select a new object, the SelectedMonkey will be updated.
If you want to track the SelectionChanged, then, it should be in the code-behind (not sure how to implement within the viewmodel, nothing about that in the docs)
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionMode="Single"
SelectionChanged="OnCollectionViewSelectionChanged">
...
</CollectionView>
And, in your Page.xaml.cs:
void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var previous = e.PreviousSelection;
var current = e.CurrentSelection;
...
}
Upvotes: 2
Reputation: 1438
It doesn't look like you set the SelectionMode property. According to the docs:
By default, CollectionView selection is disabled. However, this behavior can be changed by setting the SelectionMode property value to one of the SelectionMode enumeration members:
- None – indicates that items cannot be selected. This is the default value.
- Single – indicates that a single item can be selected, with the selected item being highlighted.
- Multiple – indicates that multiple items can be selected, with the selected items being highlighted.
Adding SelectionMode = Single
to the CollectionView will resolve your problem.
Upvotes: 1