I wondering how to change color of selection. I read official docs, topics, forum questions but it doesn't work for me.I tried 2 VisualState variant which I mark with comment.I also want to know is this any way to change size of selection and any other properties. Sometimes when I set visual states like Microsoft docs said, color of selection become transparent and I cant even see this, but all events working fine. Maybe you can advise me way in which I can just tapped on collectionview item and go to other page.
Here is my view XAML code:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Bibliomatic_MAUI_App"
xmlns:viewModels="clr-namespace:Bibliomatic_MAUI_App.ViewModels"
xmlns:models="clr-namespace:Bibliomatic_MAUI_App.Models"
x:DataType="viewModels:ArticlesViewModel"
x:Class="Bibliomatic_MAUI_App.Views.ArticleView"
Title="">
<!-- I tried this -->
<ContentPage.Resources>
<Style x:Key="BorderSelectionStyle" TargetType="Border">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor"
Value="Transparent" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ContentPage.Resources>
<StackLayout>
<ActivityIndicator HeightRequest="40"
WidthRequest="40"
IsRunning="{Binding IsBusy}"
IsVisible="{Binding IsBusy}"/>
<Border StrokeThickness="2" Padding="10" Margin="10" VerticalOptions="FillAndExpand">
<Border.StrokeShape>
<RoundRectangle CornerRadius="10"></RoundRectangle>
</Border.StrokeShape>
<StackLayout>
<CollectionView ItemsSource ="{Binding ArticleList}"
RemainingItemsThreshold="1"
RemainingItemsThresholdReachedCommand="{Binding LoadMoreArticleDataCommand}"
VerticalOptions="FillAndExpand"
SelectionMode="Single"
SelectedItem="{Binding SelectedArticle}"
x:Name="ArticlesCollectionView">
<CollectionView.Header>
<StackLayout Margin="10">
<Label Text="Articles" FontSize="Large" FontAttributes="Bold" HorizontalTextAlignment="Start"/>
<Label Text="Select articles which you like and start exploring" HorizontalTextAlignment="Start" FontSize="Caption"/>
</StackLayout>
</CollectionView.Header>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:ArticleResponce">
<Border StrokeThickness="3.5">
<Border.StrokeShape>
<RoundRectangle CornerRadius="10"></RoundRectangle>
</Border.StrokeShape>
<Grid BackgroundColor="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="dotnet_bot.svg" Aspect="AspectFill" HeightRequest="100" Grid.RowSpan="2" Grid.Column="0" Margin="5"/>
<!-- Labels -->
<StackLayout Grid.Column="1" Spacing="2" Padding="20" HorizontalOptions="FillAndExpand" Margin="20,0,10,0">
<StackLayout Orientation="Horizontal">
<Image Source="dotnet_bot.svg" WidthRequest="20" HeightRequest="20" />
<Label Text="{Binding Title}" FontSize="15" Margin="5" LineBreakMode="WordWrap" MaxLines="3" HorizontalOptions="StartAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Image Source="dotnet_bot.svg" WidthRequest="20" HeightRequest="20"/>
<Label Text="{Binding Author}" FontSize="15" Margin="5" LineBreakMode="WordWrap" MaxLines="1" HorizontalOptions="StartAndExpand"/>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Image Source="dotnet_bot.svg" WidthRequest="20" HeightRequest="20" />
<Label Text="{Binding PublishDate}" FontSize="15" Margin="5" LineBreakMode="WordWrap"/>
</StackLayout>
</StackLayout>
<!-- Second variant which I found --> <VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Yellow" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</Border>
<ActivityIndicator HeightRequest="40"
WidthRequest="40"
IsRunning="{Binding IsLoading}"
IsVisible="{Binding IsLoading}"/>
</StackLayout>
</ContentPage>
And also ViewModel code:
using Bibliomatic_MAUI_App.Models;
using Bibliomatic_MAUI_App.Services;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace Bibliomatic_MAUI_App.ViewModels
{
public partial class ArticlesViewModel : ObservableObject
{
public ObservableCollection<ArticleResponce> ArticleList { get; set; }
private List<ArticleResponce> allArticlesList;
private readonly ArticleService articleService;
private int pageSize = 20;
[ObservableProperty]
public bool isBusy;
[ObservableProperty]
public bool isLoading;
private ArticleResponce selectedArticle;
public ArticleResponce SelectedArticle
{
get => selectedArticle;
set
{
if (SetProperty(ref selectedArticle, value))
{
OnItemSelected(value);
}
}
}
public ArticlesViewModel(ArticleService articleService)
{
this.articleService = articleService;
ArticleList = new ObservableCollection<ArticleResponce>();
LoadArticleDataCommand.Execute(null);
}
private async void OnItemSelected(ArticleResponce selectedArticle)
{
if (selectedArticle != null)
{
await Shell.Current.GoToAsync($"main?title={selectedArticle.Title}");
}
}
[RelayCommand]
public async Task LoadArticleData()
{
IsBusy = true;
allArticlesList = await articleService.GetAllArticles();
var articleData = allArticlesList.Take(pageSize).ToList();
foreach (var data in articleData)
ArticleList.Add(data);
IsBusy = false;
}
[RelayCommand]
public async Task LoadMoreArticleData()
{
if (IsLoading) return;
allArticlesList = await articleService.GetAllArticles();
if (allArticlesList?.Count > 0)
{
IsLoading = true;
var articleData = allArticlesList.Skip(ArticleList.Count).Take(pageSize).ToList();
foreach (var data in articleData)
ArticleList.Add(data);
IsLoading = false;
}
}
}
}
First, I noticed that you have two Borders.
One is outside the CollectionView, another is inside the CollectionView. Which one you want to apply the style? If I understand correctly, you want to apply to the inner one. Never mind, we could just apply the Style to it using (if you define the VisualStateManager in ContentPage.Resources):
<Border StrokeThickness="3.5" Style="{x:StaticResource BorderSelectionStyle}"
Through this line we apply the style to the inner Border.
If you delete x:Key="BorderSelectionStyle"
in Style, it will apply to all Border by default.
Second
The VisualStateManager you define in ContentPage.Resources
is ok. It should work. But the second variant has no effect. Because you just put the VisualStateManager inside the Grid. So it will by default apply to the Grid.
The root element in CollectionView DataTemplate is Border. When we click the item in CollectionView, the root element Border will change the VisualStates to "Selected". Other controls in Border will not change the states.
So you could just change the position of the second variant:
<DataTemplate>
<Border>
<Grid>
</Grid>
<!--put your visualstatemanager here-->
</Border>
If you have any question, feel free to ask.