Search code examples
c#iosuicollectionviewmauiselecteditem

Programmatically setting the SelectedItem of a CollectionView is not working on iOS


I am populating a screen with a CollectionView and I'd like to preselect the SelectedItem. On Android (left screenshot), this works fine, but not on iOS (right screenshot) - only manual selection by the user seems to change the UI.

enter image description here enter image description here

To reproduce, use the standard MAUI template app, replace the XAML of the MainPage with

<?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"
             x:Class="MyMAUIApp.MainPage">
    <CollectionView ItemSizingStrategy="MeasureAllItems" BackgroundColor="Yellow"
                            ItemsSource="{Binding Items}"
                            SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                            SelectionMode="Single">
        <CollectionView.ItemsLayout>
            <GridItemsLayout Orientation="Vertical" Span="2"/>
        </CollectionView.ItemsLayout>
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Grid HeightRequest="50" WidthRequest="50">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="Selected">
                                <VisualState.Setters>
                                    <Setter Property="BackgroundColor" Value="Red"/>
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Label Text="Text" />
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>

and the C# with

using System.Collections.ObjectModel;

namespace MyMAUIApp;

public partial class MainPage : ContentPage {
    public MainPage() {
        InitializeComponent();
        BindingContext = this;

        SelectedItem = Items[0];
        OnPropertyChanged(nameof(SelectedItem));
    }

    public ObservableCollection<string> Items { get; } = new ObservableCollection<string>(new List<string> {
        "A", "B", "C", "D"
    });

    public string SelectedItem { get; set; }
}

Is this a MAUI bug? Can I avoid it somehow? In the situation where I encounter this, I have some degree of success with refreshing the Items after a short delay and/or subsequently invoking OnPropertyChanged(nameof(Items)) but not always.

Moving the code to OnAppearing(), as suggested in the comments, doesn't work:

protected override void OnAppearing() {
    base.OnAppearing();
    SelectedItem = Items[0];
    OnPropertyChanged(nameof(SelectedItem));
}

An example of how to make it work, but in a really awkward way:

public MainPage() {
    InitializeComponent();
    BindingContext = this;

    _ = Task.Run(async () => {
        await Task.Delay(100);
        Dispatcher.Dispatch(() => {
            SelectedItem = Items[0];
            OnPropertyChanged(nameof(SelectedItem));
        });
    });
}

Solution

  • Yes, it is a potential issue on iOS. For now, setting the SelectedItem property from ViewModel is not working on iOS. And it is a known issue that is being tracked in the links below, you can follow up there.

    https://github.com/dotnet/maui/issues/13059

    https://github.com/dotnet/maui/issues/13072

    As a workaround(awkaward however useful) suggested by Glorfindel like below:

        _ = Task.Run(async () => {
            await Task.Delay(100);
            Dispatcher.Dispatch(() => {
                SelectedStates = new ObservableCollection<object>(ss);
                OnPropertyChanged(nameof(SelectedStates));
            });
        });