Search code examples
androidxamlexceptionmaui

CarouselView crashes Android app when using CurrentItem in .NET MAUI


Why do I get a Target Invocation Exception as soon as I swipe my CarouselView?

CarouselView always worked since I started learning .NET MAUI but for some reason now it doesn't work anymore. I haven't done anything strange as far as I'm concerned, just a <CarouselView/> with an ItemsSource and (apparently the culprit here) a CurrentItem, which now suddenly throws an exception when it changes in any way. Either using a Command with the current item as CommandParameter, or binding the CurrentItem property directly, both throw the same exception.

System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'

enter image description here

Everything works exactly as it should, until the very moment I'll add a CurrentItem to my CarouselView. It will render the page but the app crashes as soon as I swipe to view other items in it. Either binding the CurrentItem directly or using a Command to change it:

CurrentItemChangedCommand="{Binding CarouselItemChangedCommand}"
CurrentItemChangedCommandParameter="{Binding Source={RelativeSource Self}, Path=CurrentItem}"

Both throw this exception.

Just a simple CarouselView:

<VerticalStackLayout>
    <CarouselView ItemsSource="{Binding Supports}"
                  CurrentItem="{Binding Support}"
                  IndicatorView="indicatorView"
                  IsSwipeEnabled="True"
                  Loop="False">
        <CarouselView.ItemTemplate>
            <DataTemplate x:DataType="m:Support">
                <VerticalStackLayout HorizontalOptions="Center">
                    <Frame Style="{StaticResource ItemFrameVisible}"
                            StyleClass="ItemFrame"
                            Padding="0,16,0,8"
                            Margin="0,16">
                        <VerticalStackLayout>
                            <Image Source="{Binding ImageFileSuffix, StringFormat='sp_{0}.svg'}"
                                    WidthRequest="280"/>
                            <Label Text="{Binding Title}"
                                    Style="{StaticResource TitleTiny}"
                                    StyleClass="Title"
                                    HorizontalOptions="Center"
                                    Margin="0,-56,0,0"/>
                        </VerticalStackLayout>
                    </Frame>
                </VerticalStackLayout>
            </DataTemplate>
        </CarouselView.ItemTemplate>
    </CarouselView>
    <IndicatorView SelectedIndicatorColor="{StaticResource GreenMain}"
                   IndicatorColor="{StaticResource Gray200}"
                   HorizontalOptions="Center"
                   x:Name="indicatorView"
                   MaximumVisible="14"
                   IndicatorSize="10"
                   Margin="0,12,0,0"/>
</VerticalStackLayout>

Setting Loop to true or false does not make a difference either. Removing the CurrentItem property from the CarouselView solves it but I am no longer able to use the current item in my ViewModel to perform tasks with.

ViewModel

private Support support;
public Support Support
{
    get => support;
    set => SetProperty(ref support, value);
}

public ObservableRangeCollection<Support> Supports { get; set; } = new();

BaseViewModel

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

protected bool SetProperty<TValue>(ref TValue backingField, TValue value, [CallerMemberName] string propertyName = null)
{
    if (Comparer<TValue>.Default.Compare(backingField, value) == 0)
    {
        return false;
    }

    backingField = value;

    OnPropertyChanged(propertyName);

    return true;
}

Support Model

Data such as Title, Description and ImageFileSuffix are working as the data is showing, even when swiping I can clearly see the next or previous item data before the app crashes.

[Table("Support")]
public class Support
{
    [PrimaryKey]
    public int SupportId { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string ImageFileSuffix { get; set; }
}

Call Stack

0xFFFFFFFFFFFFFFFF in Android.Runtime.JNIEnv.monodroid_debugger_unhandled_exception C#  Annotated Frame
>   0x1A in Android.Runtime.JNINativeWrapper._unhandled_exception at C:\Users\genericUser13\AppData\Local\SourceServer\bb123c2c4d433ebca46498fd0d4b0728a9cd5eedc6e5d8398523e286da2078c9\JNINativeWrapper.g.cs:12,5  C#  Non-user code
0x22 in Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLII_V at C:\Users\genericUser13\AppData\Local\SourceServer\bb123c2c4d433ebca46498fd0d4b0728a9cd5eedc6e5d8398523e286da2078c9\JNINativeWrapper.g.cs:287,26 C#  Non-user code
0x32 in System.Reflection.MethodInvoker.InterpretedInvoke   C#  Annotated Frame
0x4 in System.Reflection.MethodInvoker.InlinedInvoke    C#  Annotated Frame
0xCE in System.Reflection.RuntimeMethodInfo.Invoke  C#  Annotated Frame
0x6 in System.Reflection.MethodBase.Invoke  C#  Annotated Frame
0x31C in Microsoft.Maui.Controls.BindingExpression.ApplyCore at C:\Users\genericUser13\AppData\Local\SourceServer\62e8268ae92440603c63914b6d8a3b490f47ceaad21fcc1a5e51804834c6a305\BindingExpression.cs:188,5   C#  Non-user code
0x48 in Microsoft.Maui.Controls.BindingExpression.Apply at C:\Users\genericUser13\AppData\Local\SourceServer\62e8268ae92440603c63914b6d8a3b490f47ceaad21fcc1a5e51804834c6a305\BindingExpression.cs:56,5 C#  Non-user code
0x27 in Microsoft.Maui.Controls.Binding.Apply at C:\Users\genericUser13\AppData\Local\SourceServer\6dd575e617d2dceeb55a7d6f2e56ce8ff72455f7905177f12ed1e461a05ed3b4\Binding.cs:114,4    C#  Non-user code
0x108 in Microsoft.Maui.Controls.BindableObject.SetValueActual at C:\Users\genericUser13\AppData\Local\SourceServer\aefda1b85f6059f8ec86428ab2810170588db594e00bdaaaf0dcb2947296edc9\BindableObject.cs:529,6    C#  Non-user code
0x20C in Microsoft.Maui.Controls.BindableObject.SetValueCore at C:\Users\genericUser13\AppData\Local\SourceServer\aefda1b85f6059f8ec86428ab2810170588db594e00bdaaaf0dcb2947296edc9\BindableObject.cs:469,5  C#  Non-user code
0x5 in Microsoft.Maui.Controls.BindableObject.SetValueCore at C:\Users\genericUser13\AppData\Local\SourceServer\aefda1b85f6059f8ec86428ab2810170588db594e00bdaaaf0dcb2947296edc9\BindableObject.cs:401,7    C#  Non-user code
0x4 in Microsoft.Maui.Controls.Element.SetValueFromRenderer at C:\Users\genericUser13\AppData\Local\SourceServer\256b87211b5393e640c1d246067a29d574a61932c703f979f99c781ccba9b4c2\Element.cs:261,4  C#  Non-user code
0x61 in Microsoft.Maui.Controls.Handlers.Items.MauiCarouselRecyclerView.SetCurrentItem at C:\Users\genericUser13\AppData\Local\SourceServer\097a9d3b14092fcbf9468085ff0c7d892d23df3ce428f46e9656242399956b02\MauiCarouselRecyclerView.cs:456,4  C#  Non-user code
0x119 in Microsoft.Maui.Controls.Handlers.Items.MauiCarouselRecyclerView.Microsoft.Maui.Controls.Handlers.Items.IMauiCarouselRecyclerView.UpdateFromPosition at C:\Users\genericUser13\AppData\Local\SourceServer\097a9d3b14092fcbf9468085ff0c7d892d23df3ce428f46e9656242399956b02\MauiCarouselRecyclerView.cs:508,4    C#  Non-user code
0xB in Microsoft.Maui.Controls.Handlers.Items.CarouselViewHandler.MapPosition at C:\Users\genericUser13\AppData\Local\SourceServer\f03296ca69e671647e1230133f792254ee365c7cbaa947f2f3077fdf8d867aab\CarouselViewHandler.Android.cs:45,4 C#  Non-user code
0x21 in Microsoft.Maui.PropertyMapper<Microsoft.Maui.Controls.CarouselView,Microsoft.Maui.Controls.Handlers.Items.CarouselViewHandler>. at C:\Users\genericUser13\AppData\Local\SourceServer\00bf22cc3914378ecafa781a5dea0f3c344a52a09ca64c376cb2202c4c2e1ca3\PropertyMapper.cs:172,6   C#  Non-user code
0x17 in Microsoft.Maui.PropertyMapper.UpdatePropertyCore at C:\Users\genericUser13\AppData\Local\SourceServer\00bf22cc3914378ecafa781a5dea0f3c344a52a09ca64c376cb2202c4c2e1ca3\PropertyMapper.cs:47,4   C#  Non-user code
0x8 in Microsoft.Maui.PropertyMapper.UpdateProperty at C:\Users\genericUser13\AppData\Local\SourceServer\00bf22cc3914378ecafa781a5dea0f3c344a52a09ca64c376cb2202c4c2e1ca3\PropertyMapper.cs:72,4    C#  Non-user code
0x1C in Microsoft.Maui.Handlers.ElementHandler.UpdateValue at C:\Users\genericUser13\AppData\Local\SourceServer\13aa2389aeaa5f2f85d844344acd9ffd5bb52b2308b48237d1a1f7aba0bc87cd\ElementHandler.cs:87,4 C#  Non-user code
0x14 in Microsoft.Maui.Controls.Element.OnPropertyChanged at C:\Users\genericUser13\AppData\Local\SourceServer\256b87211b5393e640c1d246067a29d574a61932c703f979f99c781ccba9b4c2\Element.cs:383,4    C#  Non-user code
0x11B in Microsoft.Maui.Controls.BindableObject.SetValueActual at C:\Users\genericUser13\AppData\Local\SourceServer\aefda1b85f6059f8ec86428ab2810170588db594e00bdaaaf0dcb2947296edc9\BindableObject.cs:533,5    C#  Non-user code
0x20C in Microsoft.Maui.Controls.BindableObject.SetValueCore at C:\Users\genericUser13\AppData\Local\SourceServer\aefda1b85f6059f8ec86428ab2810170588db594e00bdaaaf0dcb2947296edc9\BindableObject.cs:469,5  C#  Non-user code
0x5 in Microsoft.Maui.Controls.BindableObject.SetValueCore at C:\Users\genericUser13\AppData\Local\SourceServer\aefda1b85f6059f8ec86428ab2810170588db594e00bdaaaf0dcb2947296edc9\BindableObject.cs:401,7    C#  Non-user code
0x4 in Microsoft.Maui.Controls.Element.SetValueFromRenderer at C:\Users\genericUser13\AppData\Local\SourceServer\256b87211b5393e640c1d246067a29d574a61932c703f979f99c781ccba9b4c2\Element.cs:261,4  C#  Non-user code
0x3A in Microsoft.Maui.Controls.Handlers.Items.MauiCarouselRecyclerView.UpdatePosition at C:\Users\genericUser13\AppData\Local\SourceServer\097a9d3b14092fcbf9468085ff0c7d892d23df3ce428f46e9656242399956b02\MauiCarouselRecyclerView.cs:447,5  C#  Non-user code
0x42 in Microsoft.Maui.Controls.Handlers.Items.MauiCarouselRecyclerView.CarouselViewScrolled at C:\Users\genericUser13\AppData\Local\SourceServer\097a9d3b14092fcbf9468085ff0c7d892d23df3ce428f46e9656242399956b02\MauiCarouselRecyclerView.cs:417,4    C#  Non-user code
0xE in Microsoft.Maui.Controls.ItemsView.SendScrolled at C:\Users\genericUser13\AppData\Local\SourceServer\4fe8e933f734ce9480a3c27fc094f2c3ee717b35003a01f015cbf8402e421275\ItemsView.cs:225,4  C#  Non-user code
0xA9 in Microsoft.Maui.Controls.Handlers.Items.RecyclerViewScrollListener<Microsoft.Maui.Controls.CarouselView,Microsoft.Maui.Controls.Handlers.Items.IItemsViewSource>.OnScrolled at C:\Users\genericUser13\AppData\Local\SourceServer\b212eda26d70d29f6668cbfaaf86f1a91cb82a7f5cac658b3d34bb2e99f6fb81\RecyclerViewScrollListener.cs:55,4 C#  Non-user code
0x4 in Microsoft.Maui.Controls.Handlers.Items.CarouselViewOnScrollListener.OnScrolled at C:\Users\genericUser13\AppData\Local\SourceServer\e515b26a062e48cba2b6fd7d25c47f0cbd339d0a041b04aabf55197dc71a562f\CarouselViewOnScrollListener.cs:33,4    C#  Non-user code
0x14 in AndroidX.RecyclerView.Widget.RecyclerView.OnScrollListener.n_OnScrolled_Landroidx_recyclerview_widget_RecyclerView_II at C:\a\_work\3\s\generated\androidx.recyclerview.recyclerview\obj\Release\net6.0-android\generated\src\AndroidX.RecyclerView.Widget.RecyclerView.cs:9152,5   C#  Annotated Frame
0xD in Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLII_V at C:\Users\genericUser13\AppData\Local\SourceServer\bb123c2c4d433ebca46498fd0d4b0728a9cd5eedc6e5d8398523e286da2078c9\JNINativeWrapper.g.cs:286,5   C#  Non-user code

Solution

  • I could reproduce your problem, the problem is in the function protected bool SetProperty<TValue>() of BaseViewModel.

    Please try to change it to the following code:

        bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Object.Equals(storage, value))
                return false;
            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    
        //protected bool SetProperty<TValue>(ref TValue backingField, TValue value, [CallerMemberName] string propertyName = null)
        //{
    
        // throw error here
    
        //    if (Comparer<TValue>.Default.Compare(backingField, value) == 0)    
        //    {
        //        return false;
        //    }
    
        //    backingField = value;
    
        //    OnPropertyChanged(propertyName);
    
        //    return true;
        //}
    

    Note:

    Please don't forget to add symbol } for your binding, just as ToolmakerSteve mentioned.

     CurrentItem="{Binding Support}"