'Updating ListView from database: 'No installed components were detected. Child collection must not be modified during measure or arrange.'

I am currently working on a simple task management MVVM application.

Minimal code of the project:

MainPage.xaml

<Page x:Class="TestArea.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:local="using:TestArea"
      xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
      xmlns:core="using:Microsoft.Xaml.Interactions.Core"
      mc:Ignorable="d"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid>
        <ListView x:Name="TasksListView"
                  Grid.Row="0"
                  ItemsSource="{x:Bind ViewModel.Tasks, Mode=OneWay}"
                  HorizontalAlignment="Stretch"
                  VerticalAlignment="Stretch">

            <interactivity:Interaction.Behaviors>
                <core:EventTriggerBehavior EventName="Loaded">
                    <core:EventTriggerBehavior.Actions>
                        <core:InvokeCommandAction 
                            Command="{x:Bind ViewModel.OnLoadedCommand, Mode=OneWay}" />
                    </core:EventTriggerBehavior.Actions>
                </core:EventTriggerBehavior>
            </interactivity:Interaction.Behaviors>

            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:Task">
                    <Border HorizontalAlignment="Stretch"
                            BorderBrush="Gray"
                            BorderThickness="1"
                            Background="White"
                            MinHeight="55">
                        <CheckBox VerticalAlignment="Stretch"
                                  HorizontalAlignment="Stretch"
                                  VerticalContentAlignment="Center"
                                  Content="{Binding Description, Mode=OneWay}"
                                  IsChecked="{Binding IsCompleted, Mode=OneWay}">
                            <interactivity:Interaction.Behaviors>
                                <core:EventTriggerBehavior EventName="Checked">
                                    <core:EventTriggerBehavior.Actions>
                                        <core:InvokeCommandAction 
                                            Command="{Binding ElementName=TasksListView, Path=DataContext.OnCheckedTaskCommand}"
                                            CommandParameter="{x:Bind Mode=OneWay}" />
                                    </core:EventTriggerBehavior.Actions>
                                </core:EventTriggerBehavior>
                            </interactivity:Interaction.Behaviors>
                        </CheckBox>
                    </Border>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

MainPage.xaml.cs

namespace TestArea;

public sealed partial class MainPage
{
    public MainPage()
    {
        InitializeComponent();
        ViewModel = new MainPageViewModel();
    }

    public MainPageViewModel ViewModel
    {
        get => (MainPageViewModel) DataContext; 
        private set => DataContext = value;
    }
}

MainPageViewModel.cs

using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;
using Windows.UI.Xaml;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;

namespace TestArea;

public class MainPageViewModel : ObservableObject
{
    private DataContext _db;

    public MainPageViewModel()
    {
        _db = new DataContext();

        // Add items in db
        for (int i = 1; i <= 10; i++)
        {
            var newTask = new Task
            {
                Id = i,
                Description = $"Task-{i}",
                IsCompleted = false
            };
            _db.Tasks.Add(newTask);
        }
        _db.SaveChanges();
        Refresh();

        OnLoadedCommand = new RelayCommand<RoutedEventArgs>(OnLoaded);
        OnCheckedTaskCommand = new RelayCommand<Task>(OnCheckedTask);
    }

    private void Refresh()
    {
        Tasks = _db.Tasks.ToList();
    }

    private List<Task> _tasks;

    public List<Task> Tasks
    {
        get => _tasks;
        set => SetProperty(ref _tasks, value);
    }

    public ICommand OnLoadedCommand { get; }

    private void OnLoaded(RoutedEventArgs e)
    {
        // Get data from db
        Refresh();
    }

    public ICommand OnCheckedTaskCommand { get; }

    private void OnCheckedTask(Task task)
    {
        // Find in db task with id == task.Id
        var suitableTaskFromDb = _db.Tasks.First(taskInDb => taskInDb.Id == task.Id);
        if (suitableTaskFromDb != null)
        {
            // Mark as completed
            suitableTaskFromDb.IsCompleted = true;
            // Save changes and refresh view
            _db.SaveChanges();
            Refresh();
        }
    }
}

TaskModel.cs

namespace TestArea;

public class Task
{
    public int Id { get; set; }

    public string Description { get; set; }

    public bool IsCompleted { get; set; }
}

DataContext.cs

using System;
using System.IO;
using Microsoft.EntityFrameworkCore;

namespace TestArea;

public sealed class DataContext : DbContext
{
    public DataContext()
    {
        var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
        DbPath = Path.Combine(path, "TestApp.db");
        Database.EnsureCreated();
    }

    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlite($"Data Source={DbPath}");
    }

    public string DbPath { get; }

    public DbSet<Task> Tasks { get; set; }
}

References:

Microsoft.EntityFrameworkCore.Sqlite
Microsoft.EntityFrameworkCore.Tools
Microsoft.NETCore.UniversalWindowsPlatform
Microsoft.Toolkit.Mvvm
Microsoft.UI.Xaml.Markup
Microsoft.Xaml.Behaviors.Uwp.Managed
Universal Windows

To store data I am using SQLite database and Entity Framework library. In the UI part I have a ListView which contains tasks that are presented as CheckBox controls. If the task is completed - you need to check the checkbox. Loading the records themselves from the database seems to be in okay, I can see the created records in ListView. However, the problem arises with the IsChecked property and saving/reading from the database IsCompleted parameter. At least I understand that, because the problem came after I added OnCheckedTaskCommand.

When I click on the checkbox, I get the following exception:

System.Exception: 'No installed components were detected.
Child collection must not be modified during measure or arrange.'
This exception was originally thrown at this call stack:
    [External Code]
    TestArea.MainPageViewModel.Tasks.set(System.Collections.Generic.List<TestArea.Task>) in MainPageViewModel.cs
    TestArea.MainPageViewModel.Refresh() in MainPageViewModel.cs
    TestArea.MainPageViewModel.OnCheckedTask(TestArea.Task) in MainPageViewModel.cs
    [External Code]

What could be the cause?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source