Forum Xamarin.Forms

How can I prevent ListView from flickering (in GTK only) when making any changes?

I have a Xamarin.Forms build which contains a ListView bound to an ObservableCollection. My end goal is to regularly update this ObservableCollection using a MessagingCenter subscription which is triggered by an HTTPRequest elsewhere in the app's code, but this is beside the point. I'm developing the app for use on a Raspberry Pi, and as such the GTK support has been great, but I've noticed that when adding or removing any items within the ObservableCollection, the entire list flickers. This issue only occurs in the GTK build, however. Updates are smooth in Android.

I've seen solutions for Android using things like DoubleBuffer, but since this seems like a pretty complex solution and I was having trouble understanding exactly how to implement it, I wanted to see if anyone was aware of an easier fix that was GTK specific or at least of where I could start looking for issues within the GTK build.

It should be noted that I've tried adding and removing list items from just about everywhere, including locally within the ListPageViewModel (ignoring MessagingCenter). I've included the code for the ViewModel containing the ObservableCollection and the MessagingCenter Subscription as well as the ListPage xaml. Any thoughts would be appreciated.

ListPageViewModel:

using MyApp.Models;
using MyApp.Views;
using System.Collections.ObjectModel;
using Xamarin.Forms;

namespace MyApp.ViewModels
{
    public class ListPageViewModel
    {
        public ObservableCollection<MyItem> MyList { get; private set; } = new ObservableCollection<MyItem>();
        public MyItem SelectedMyItem { get; set; }
        INavigation Navigation;
        ListUpdater listUpdater; //This is a separate class which will be doing all of the comparisons and adding/removing on each new message

        public ListPageViewModel(INavigation MyListNavigation)
        {
            Navigation = MyListNavigation;
            listUpdater = new ListUpdater(MyList); //passing the list by reference into the updater class
            MessagingCenter.Subscribe<object, ObservableCollection<MyItem>>(Application.Current, Constants._listUpdateContract, (sender, argument) =>
            {

                listUpdater.AddToList(); //This method of the ListUpdater class currently only adds a new MyItem to the list
                          //I have also added and removed MyItems locally, inside a loop, without depending on the MessagingCenter      
            });
        }
    }
}

XAML for ListView:

<ContentPage.Content>
        <StackLayout Orientation="Horizontal">
            <ListView x:Name="MyList"
                      HasUnevenRows="True"
                      SeparatorVisibility="Default"
                      VerticalOptions="FillAndExpand"
                      SelectedItem="{Binding SelectedMyItem, Mode=TwoWay}"
                      ItemsSource="{Binding MyItems}"
                      ItemSelected="myList_ItemSelected">

                <ListView.BackgroundColor>
                    <OnPlatform x:TypeArguments="Color">
                        <On Platform="GTK" Value="White" />
                    </OnPlatform>
                </ListView.BackgroundColor>

                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout Orientation="Vertical"
                                         VerticalOptions="CenterAndExpand">
                                <Grid HorizontalOptions="Center"
                                      VerticalOptions="FillAndExpand">
                                    <Label Grid.Row="0"
                                           Grid.Column="0"
                                           HorizontalOptions="Center"
                                           Text="{Binding TypeAndId}"
                                           FontSize="Medium"/>
                                </Grid>
                                <Grid HorizontalOptions="Center"
                                      VerticalOptions="FillAndExpand">
                                    <Label Grid.Row="0" 
                                           Grid.Column="0"
                                           HorizontalOptions="End"
                                           Text="{Binding Current_Id, StringFormat='Current: {0}'}"/>
                                    <Label Grid.Row="0" 
                                           Grid.Column="1"
                                           HorizontalOptions="Center"
                                           Text="{Binding Status}"
                                           TextColor="{Binding Status, Converter={StaticResource StatusToColorConverter}}"/>
                                    <StackLayout Grid.Row="0"
                                                 Grid.Column="2"
                                                 Orientation="Vertical"
                                                 VerticalOptions="Center">
                                        <Label Text="{Binding Latitude}"/>
                                        <Label Text="{Binding Longitude}"/>
                                    </StackLayout>
                                </Grid>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
Sign In or Register to comment.