I want to have a pre-selected item in the collection view but it is not working. Am sending data from a viewmodel to the collection view. i want to have one item preselected in the collection view. I need help here in xamarin. here is my code
Xaml
<CollectionView x:Name="WorkerFlockView" ItemsSource="{Binding WorkerFlockDetails}" SelectedItem="{Binding SelectedFlock}" SelectionMode="Single" SelectionChangedCommand="{Binding ViewFlockControlPointsCommand}" HeightRequest="100">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" ItemSpacing="10" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Frame Margin="0,0,0,0" Padding="0" HorizontalOptions="CenterAndExpand" BackgroundColor="#F7F7F7" Opacity="0.93" HasShadow="{OnPlatform Android=true, iOS=false}" CornerRadius="0" IsClippedToBounds="True" >
<StackLayout Orientation="Vertical" Opacity="1">
<StackLayout HeightRequest="15" BackgroundColor="#105CA5"></StackLayout>
<StackLayout Orientation="Vertical" Padding="10,0,10,0" VerticalOptions="CenterAndExpand">
<StackLayout Orientation="Horizontal">
<Label Text="Flock" TextColor="#105CA5"></Label>
<Label Text="{Binding Flock_name}"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Farm" TextColor="#105CA5"></Label>
<Label Text="{Binding Farm_name}"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="House" TextColor="#105CA5"></Label>
<Label Text="{Binding House_name}"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Age" TextColor="#105CA5"></Label>
<Label Text="{Binding Flock_age}"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Bird Type" TextColor="#105CA5"></Label>
<Label Text="{Binding Bird_type}"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Number of birds" TextColor="#105CA5"></Label>
<Label Text="{Binding Number_of_birds}"></Label>
</StackLayout>
</StackLayout>
</StackLayout>
</Frame>
<VisualStateManager.VisualStateGroups >
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Blue" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
View Model
class HomeWorkerViewModel : INotifyPropertyChanged {
public HomeWorkerViewModel(){
WorkerFlockDetails = new ObservableCollection<WorkerFlock>();
selectedFlock = WorkerFlockDetails.Skip(3).FirstOrDefault();
//function for adding information
Init();
}
//Populate WorkerFlockDetails with data
function Init()
public ObservableCollection<WorkerFlock> workerFlockDetails;
public ObservableCollection<WorkerFlock> WorkerFlockDetails
{
get => workerFlockDetails;
set
{
workerFlockDetails = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(WorkerFlockDetails)));
}
}
private WorkerFlock selectedFlock { get; set; }
public WorkerFlock SelectedFlock
{
get { return selectedFlock; }
set
{
if (selectedFlock != value)
{
try
{
//Feed = selectedFlock.Feed_intake.ToString() " Kg";
selectedFlock = value;
}
catch
{
}
}
}
}
}
CodePudding user response:
There are a few things:
The class ObservableCollection automatically implements a Notify method, so you don't need a private field and calling the
PropertyChanged
public ObservableCollection WorkerFlockDetails { get; set; }
You should call PropertyChanged when modifying the
SelectedFlock
private WorkerFlock selectedFlock; public WorkerFlock SelectedFlock { get => selectedFlock set { if (selectedFlock != value) { try { //Feed = selectedFlock.Feed_intake.ToString() " Kg"; selectedFlock = value; } catch { } finally { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedFlock))); } } } }
Let's move to the constructor. If the
Init()
method fills your ObservableCollection with data, you should call that before selecting an Item, otherwise, the collection will be empty
And when changing the Selection using code, you should call the public property instead of the private, because that one Notifies the UI that it changed
public HomeWorkerViewModel(){
WorkerFlockDetails = new ObservableCollection<WorkerFlock>();
//Call init before selection
//function for adding information.
Init();
//Use public property
SelectedFlock = WorkerFlockDetails.Skip(3).FirstOrDefault();
}
Happy coding!