Home > OS >  net maui app crashes on basic delete from list
net maui app crashes on basic delete from list

Time:05-24

I am new to .net Maui (and Xamarin forms), but I am trying to get an example of MVVM working as obtained from a video on https://www.youtube.com/watch?v=oNIvnCNzAqU

My problem is that when I click on the bin icon the app crashes totally.

Here is the relevant code TodoListViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace MauiApp1
{
  public class TodoListViewModel : BindableObject
  {

    public ObservableCollection<TodoItem> TodoItems { get; set; }


    public TodoListViewModel()
    {
      TodoItems = new ObservableCollection<TodoItem>
      {
        //test
        //new TodoItem("todo 1", false),
        //new TodoItem("todo 2", true),
        //new TodoItem("todo 3", false)
      };
    }

    string newTodoText = string.Empty;
    public string NewTodoText 
    {
      get { return newTodoText; }
      
      set
      {
        if (value == newTodoText) return;
        newTodoText = value;
        OnPropertyChanged();
      } 
    
    }

    public ICommand AddTodoCommand => new Command( AddTodoItem );
    public void AddTodoItem()
    {
      //Console.WriteLine(NewTodoText);
      TodoItems.Add(new TodoItem(NewTodoText, false));

      //clear entry and refocus
      NewTodoText = string.Empty;
      

      //Todo.Focus();

      ////dismiss keyboard
      //Todo.IsEnabled = false;
      //Todo.IsEnabled = true;
    }

    public ICommand RemoveTodoCommand => new Command( RemoveTodoItem );
    void RemoveTodoItem(Object o)
    {
      TodoItem todoItemBeingRemoved = o as TodoItem;
      TodoItems.Remove(todoItemBeingRemoved);
    }
  }
}

and the xaml MainPage.xaml

<?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:MauiApp1"
             x:Class="MauiApp1.MainPage"
             >

  <ContentPage.BindingContext>
    <local:TodoListViewModel />
  </ContentPage.BindingContext>

  <Grid RowDefinitions="Auto, Auto, Auto, *">

    <Entry
      Grid.Row="0"
      FontSize="24"
      Placeholder="Enter a ToDo"
      Text="{Binding NewTodoText}"
      ReturnCommand="{Binding AddTodoCommand}"
    />

    <Button 
        Grid.Row="1" 
        Margin="10"
        Padding="10"
        FontSize="24"
        Text="Add a Todo" 
        Command="{Binding AddTodoCommand}"
    />

    <ListView 
      Grid.Row="2"
      x:Name="TodoList" 
      ItemsSource="{Binding TodoItems}">

      <ListView.ItemTemplate>

        <DataTemplate>
          <ViewCell>
            
            <Grid 
              Margin="10, 0, 0, 0"
              
              ColumnDefinitions="auto, auto, *">
              <CheckBox 
                Grid.Column="0"
                  IsChecked="{Binding Complete}" />

              <Label 
                  Grid.Column="1" 
                  Text="{Binding TodoText}" 
                  FontSize="24" />

                <ImageButton 
                Grid.Column="2" 
                HorizontalOptions="End"  
                Source="delete.png" 
                Scale="0.7" 
                BackgroundColor="Transparent"
                Command="{Binding Path=BindingContext.RemoveTodoCommand, Source={x:Reference TodoList}}"
                CommandParameter="{Binding .}"/>
              
            </Grid>  

          </ViewCell>

        </DataTemplate>

      </ListView.ItemTemplate>

    </ListView>

  </Grid>

</ContentPage>
 

I've tried debugging this and the ObservableCollections seems to work (and why wouldn't it, this is fairly robust tech) but the linkage to the xaml seems to be what is failing.

So I add two items and delete the first one, crash! and here is the voluminous error output from the immediate window:

> am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -n "com.companyname.mauiapp1/crc64e632a077a20c694c.MainActivity"
> Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.companyname.mauiapp1/crc64e632a077a20c694c.MainActivity }
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/MauiApp1.dll
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/Mono.Android.dll [External]
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/System.Runtime.dll [External]
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/Java.Interop.dll [External]
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/System.Collections.dll [External]
Resolved pending breakpoint for 'Android.Runtime.JNIEnv.RegisterJniNatives(System.IntPtr, System.Int32, System.IntPtr, System.IntPtr, System.Int32)' to /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNIEnv.cs:124 [0x00000].
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/System.Threading.dll [External]
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/System.Runtime.InteropServices.dll [External]
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/System.Threading.Thread.dll [External]
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/System.Diagnostics.StackTrace.dll [External]
Loaded assembly: data-0x756590c69030 [External]
Loaded assembly: data-0x756590c59020 [External]
Loaded assembly: data-0x75637a336040 [External]
Loaded assembly: data-0x756590c79040 [External]
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/netstandard.dll [External]
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/System.Linq.dll [External]
Loaded assembly: /data/data/com.companyname.mauiapp1/files/.__override__/System.Collections.Concurrent.dll [External]
Resolved pending breakpoint for 'Xamarin.HotReload.HotReloadAgent.BreakpointSendToIde(System.String)' to D:\a\_work\1\s\HotReload\Source\Xamarin.HotReload.Agent\HotReloadAgent.cs:419 [0x00000].

...hundreds of lines removed

[nyname.mauiapp] runtime.cc:663]   at int androidx.recyclerview.widget.LinearLayoutManager.fill(androidx.recyclerview.widget.RecyclerView$Recycler, androidx.recyclerview.widget.LinearLayoutManager$LayoutState, androidx.recyclerview.widget.RecyclerView$State, boolean) (LinearLayoutManager.java:1591)
[nyname.mauiapp] runtime.cc:663]   at void androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(androidx.recyclerview.widget.RecyclerView$Recycler, androidx.recyclerview.widget.RecyclerView$State) (LinearLayoutManager.java:668)
[nyname.mauiapp] runtime.cc:663]   at void androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2() (RecyclerView.java:4309)
[nyname.mauiapp] runtime.cc:663]   at void androidx.recyclerview.widget.RecyclerView.dispatchLayout() (RecyclerView.java:4012)
[nyname.mauiapp] runtime.cc:663]   at void androidx.recyclerview.widget.RecyclerView.onLayout(boolean, int, int, int, int) (RecyclerView.java:4578)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void androidx.viewpager2.widget.ViewPager2.onLayout(boolean, int, int, int, int) (ViewPager2.java:527)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(androidx.coordinatorlayout.widget.CoordinatorLayout, android.view.View, int) (HeaderScrollingViewBehavior.java:148)
[nyname.mauiapp] runtime.cc:663]   at boolean com.google.android.material.appbar.ViewOffsetBehavior.onLayoutChild(androidx.coordinatorlayout.widget.CoordinatorLayout, android.view.View, int) (ViewOffsetBehavior.java:43)
[nyname.mauiapp] runtime.cc:663]   at boolean com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior.onLayoutChild(androidx.coordinatorlayout.widget.CoordinatorLayout, android.view.View, int) (AppBarLayout.java:2122)
[nyname.mauiapp] runtime.cc:663]   at void androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(boolean, int, int, int, int) (CoordinatorLayout.java:953)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) (FrameLayout.java:332)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.onLayout(boolean, int, int, int, int) (FrameLayout.java:270)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.LinearLayout.setChildFrame(android.view.View, int, int, int, int) (LinearLayout.java:1829)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.LinearLayout.layoutVertical(int, int, int, int) (LinearLayout.java:1673)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.LinearLayout.onLayout(boolean, int, int, int, int) (LinearLayout.java:1582)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) (FrameLayout.java:332)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.onLayout(boolean, int, int, int, int) (FrameLayout.java:270)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void androidx.drawerlayout.widget.DrawerLayout.onLayout(boolean, int, int, int, int) (DrawerLayout.java:1263)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.LinearLayout.setChildFrame(android.view.View, int, int, int, int) (LinearLayout.java:1829)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.LinearLayout.layoutHorizontal(int, int, int, int) (LinearLayout.java:1818)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.LinearLayout.onLayout(boolean, int, int, int, int) (LinearLayout.java:1584)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) (FrameLayout.java:332)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.onLayout(boolean, int, int, int, int) (FrameLayout.java:270)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) (FrameLayout.java:332)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.onLayout(boolean, int, int, int, int) (FrameLayout.java:270)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) (FrameLayout.java:332)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.onLayout(boolean, int, int, int, int) (FrameLayout.java:270)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.LinearLayout.setChildFrame(android.view.View, int, int, int, int) (LinearLayout.java:1829)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.LinearLayout.layoutVertical(int, int, int, int) (LinearLayout.java:1673)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.LinearLayout.onLayout(boolean, int, int, int, int) (LinearLayout.java:1582)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[nyname.mauiapp] runtime.cc:663]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6389)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) (FrameLayout.java:332)
[nyname.mauiapp] runtime.cc:663]   at void android.widget.FrameLayout.onLayout(boolean, int, int, int, int) (FrameLayout.java:270)
[nyname.mauiapp] runtime.cc:663]   at void com.android.internal.policy.DecorView.onLayout(boolean, int, int, int, int) (DecorView.java:784)
[nyname.mauiapp] runtime.cc:663]   at void android.view.View.layout(int, int, int, int) (View.java:22844)
[libc] Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 31838 (nyname.mauiapp1), pid 31838 (nyname.mauiapp1)

Told you it was voluminous and I can't figure out anything. I mean what is anyone supposed to do with all that!!!

This is probably a very often used use pattern, but I just cannot figure out what I've done wrong. Any pointers gratefully receieved and hopefully it isn't a spelling error... :sigh

G

CodePudding user response:

ListView is one of 4 "legacy" Renderer-based views.

I recommend using CollectionView instead. Some properties will be different, but in your example, only TWO changes ared needed:

  1. Change ListView to CollectionView.
  2. Remove <ViewCell> from the ItemTemplate. (Or will crash with "Can't cast" exception.)
        <CollectionView Grid.Row="2" x:Name="TodoList" ItemsSource="{Binding TodoItems}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                  <!-- REMOVED ViewCell -->
                    <Grid Margin="10, 0, 0, 0" ... />
                        ...
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
  • Verified that this version works (does not crash when delete first item) on Android.
  • Related