I'm experiencing a really strange issue trying to print an observableCollection of object in a CollectionView. I want to have a grid of 42 block and in each one print a number from 1 to 42. When I click on a block, I want its background to turn green.
Here is my code (pretty simple) :
Model :
public class Case
{
public int Id { get; set; }
public string ColorToPrint { get; set; }
public Case(int id, string color)
{
Id = id;
ColorToPrint = color;
}
}
ViewModel :
public ICommand SelectionChangedCommand { get; set; }
public GridViewModel()
{
Cases = new ObservableCollection<Case>();
for (int i=1; i<=42; i++)
{
Case c = new Case(i, "Grey");
Cases.Add(c);
}
SelectionChangedCommand = new Command(OnSelectionChanged);
}
private void OnSelectionChanged()
{
Case c = new Case(SelectedCase.Id, "Green");
Cases[SelectedCase.Id - 1] = c;
}
private ObservableCollection<Case> cases;
public ObservableCollection<Case> Cases
{
get => cases;
set
{
cases = value;
OnPropertyChanged(nameof(Cases));
}
}
private Case selectedCase;
public Case SelectedCase
{
get => selectedCase;
set
{
selectedCase = value;
OnPropertyChanged(nameof(SelectedCase));
}
}
}
And my page :
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<CollectionView ItemsSource="{Binding Cases}"
SelectionMode="Single"
SelectedItem="{Binding SelectedCase}"
SelectionChangedCommand="{Binding SelectionChangedCommand}"
Grid.Column="0"
Grid.Row="0"
ItemsLayout="VerticalGrid, 6"
Margin="20">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame Padding="2"
BackgroundColor="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Transparent"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Frame BorderColor="Black"
MinimumHeightRequest="20"
CornerRadius="5"
BackgroundColor="{Binding ColorToPrint}">
<Label Text="{Binding Id}"
TextColor="Black"
FontAttributes="Bold"
FontSize="15"
HorizontalOptions="Center"
VerticalOptions="Center"
/>
</Frame>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
Of course, on my page.cs the viewmodel is define as the bindingContext.
So this code is working pretty well but I got a strange behaviour erasing the number in a block if I click on it (color change well) and reapearing if I click on another block. It seems also that this behaviour is happing ramdomly and not all time.
I've been lokking for a solution for my entire afternoon and I would really appreciate a bit of help on that.
Thanks everyone and excuse my pretty bad english ..
Tried different way of updating my observablecollection and also a lot of things with the propertychange event
This issue can be replicated on my side. To fix the issue, you can replace the outside Frame
of the items in CollectionView
with Grid
or StackLayout
like below:
<CollectionView ItemsSource="{Binding Cases}"
SelectionMode="Single"
SelectedItem="{Binding SelectedCase}"
SelectionChangedCommand="{Binding SelectionChangedCommand}"
Grid.Column="0"
Grid.Row="0"
ItemsLayout="VerticalGrid, 6"
Margin="20">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="2"
>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Transparent"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Frame BorderColor="Black"
MinimumHeightRequest="40"
CornerRadius="5"
BackgroundColor="{Binding ColorToPrint}">
<Label Text="{Binding Id}"
TextColor="Black"
FontAttributes="Bold"
FontSize="15"
HorizontalOptions="Center"
VerticalOptions="Center"
/>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>