Search code examples
c#xamluwprealm

ListView not updating on CollectionChanged


I am starting to play with Realm, and I am trying to bind a collection from the Realm database to a ListView. The binding works fine, but my ListView does not update when adding new items. My understanding is that IRealmCollection<> implements INotifyCollectionChanged and INotifyPropertyChanged events.

Here is a simple application to reproduce the issue:

View:

<Page x:Class="App3.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="using:App3"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <Button Click="ButtonBase_OnClick" Content="Add" />
            <ListView x:Name="ListView">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Id}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackPanel>
    </Grid>
</Page>

CodeBehind:

namespace App3
{
    public class Thing : RealmObject
    {
        public string Id { get; set; } = Guid.NewGuid().ToString();
    }

    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        private Realm _realm;
        private IRealmCollection<Thing> things;

        public MainPage()
        {
            this.InitializeComponent();

            _realm = Realm.GetInstance();
            things = (IRealmCollection<Thing>)_realm.All<Thing>();

            ListView.ItemsSource = things;
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            _realm.Write(() =>
            {
                var thing = new Thing();
                _realm.Add(thing);
            });
        }
    }
}

I normally use MVVM (Template10), but this is a simple application to demonstrate the issue. Clicking the Add button adds an item to the database, but the ListView only updates when the application is first loaded. I have read similar questions, but I have not been able to find an answer that works yet. Inverse Relationships and UI-Update not working? is the closest I have found yet, but still does not fix the issue.

EDIT

I can force it to rebind like so:

ListView.ItemsSource = null;
ListView.ItemsSource = things;

But that is not optimal. I am trying to take advantage of Realm's "live objects" where the collection should always know when items are changed or added.

EDIT 2

Setting BindingMode=OneWay in code-behind also does not change the behavior:

_realm = Realm.GetInstance();
things = (IRealmCollection<Thing>)_realm.All<Thing>();

var binding = new Binding
{
    Source = things,
    Mode = BindingMode.OneWay
};

ListView.SetBinding(ListView.ItemsSourceProperty, binding);

SOLUTION

It turned out to be a known issue in IRealmCollection: https://github.com/realm/realm-dotnet/issues/1461#issuecomment-312489046 which is fixed in Realm 1.6.0. I have updated to the pre-release NuGet package and can confirm that the ListView now updates as expected.


Solution

  • Set Mode=OneWay in Binding

    Method 1: In Xaml

    <ListView ItemsSource="{x:Bind things, Mode=OneWay}" />
    

    Method 2: In Code Behind

    Binding myBind = new Binding();
    myBind.Source = things;
    myBind.Mode = BindingMode.OneWay;
    myListView.SetBinding(ListView.ItemsSourceProperty, myBind);
    

    It is a bug in IRealmCollection. You can use Prerelease Nuget to solve it.

    For more info:
    IRealmCollection does not update UWP ListView
    GitHub Issue: IRealmCollection does not update UWP ListView