3
votes

I am coding a Xamarin PCL app but I keep getting this error

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

And sometimes

System.Reflection.TargetInvocationException: < Timeout exceeded getting exception details >

It only occurs when I tap the image binded to the OptionClick line in the XAML and in C# is new Command((sender) => ShowOptionActions(message.Id, message.Sender_Id, sender)) I tried changing it to DisplayAlert instead of the method, but anything I put made the error appear when I clicked it.

It also only appeared on Android, it works fine on iOS. They both use the same code.

My ObjectMessage class is

public class MessageObject : INotifyPropertyChanged
{

    private int Id = -1;
    private Command optionCommandValue;
    private string bodyValue = String.Empty;
    private Color bodyColorValue = Color.Black;
    private string likeImageSource = String.Empty;
    private Command likeCommandValue;
    private string timestampValue = String.Empty;
    private Boolean showBannersValue = true;

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private MessageObject(int id, Command optionCommand, string body, string likeImage, Command likeCommand, string timestamp)
    {
        Id = id;
        optionCommandValue = optionCommand;
        bodyValue = body;
        bodyColorValue = Color.Black;
        likeImageSource = likeImage;
        likeCommandValue = likeCommand;
        timestampValue = timestamp;
        showBannersValue = true;
    }

    public static MessageObject CreateMessage(int id, Command optionCommand, string body, string likeImage, Command likeCommand, string timestamp)
    {
        return new MessageObject(id, optionCommand, body, likeImage, likeCommand, timestamp);
    }

    public int ID
    {
        get
        {
            return this.Id;
        }
    }

    public Command OptionClick
    {
        get
        {
            return this.optionCommandValue;
        }

        set
        {
            if (value != this.optionCommandValue)
            {
                this.optionCommandValue = value;
                NotifyPropertyChanged();
            }
        }
    }

    public string Body
    {
        get
        {
            return this.bodyValue;
        }

        set
        {
            if (value != this.bodyValue)
            {
                this.bodyValue = value;
                NotifyPropertyChanged();
            }
        }
    }

    public Color BodyColor
    {
        get
        {
            return this.bodyColorValue;
        }

        set
        {
            if (value != this.bodyColorValue)
            {
                this.bodyColorValue = value;
                NotifyPropertyChanged();
            }
        }
    }

    public string LikeImageSource
    {
        get
        {
            return this.likeImageSource;
        }

        set
        {
            if (value != this.likeImageSource)
            {
                this.likeImageSource = value;
                NotifyPropertyChanged();
            }
        }
    }

    public Command LikeClick
    {
        get
        {
            return this.likeCommandValue;
        }

        set
        {
            if (value != this.likeCommandValue)
            {
                this.likeCommandValue = value;
                NotifyPropertyChanged();
            }
        }
    }

    public string Timestamp
    {
        get
        {
            return this.timestampValue;
        }

        set
        {
            if(value != this.timestampValue)
            {
                this.timestampValue = value;
                NotifyPropertyChanged();
            }
        }
    }

    public Boolean ShowBanners
    {
        get
        {
            return this.showBannersValue;
        }

        set
        {
            if (value != this.showBannersValue)
            {
                this.showBannersValue = value;
                NotifyPropertyChanged();
            }
        }
    }
}

I create a MessageObject using

MessageObject mo = MessageObject.CreateMessage(
                message.Id,
                new Command((sender) => ShowOptionActions(message.Id, message.Sender_Id, sender)),
                message.Body,
                message.Liked == 0 ? "like_icon.png" : "liked_icon.png",
                new Command((sender) => LikeMessageClick(message.Id, sender)),
                dateFormat.ToString("MMMM dd, yyyy HH:mm"));

my XAML is

<ContentPage.Content>
    <StackLayout BackgroundColor="#7ed6df">
        <local:PostListView x:Name="MessageView" HasUnevenRows="True" IsPullToRefreshEnabled="True" Refreshing="MessageView_Refreshing" SeparatorVisibility="None" BackgroundColor="#7ed6df">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <local:PostViewCell>
                        <StackLayout>
                            <StackLayout x:Name="MessageLayout" BackgroundColor="White" Margin="10, 10, 10, 10" Padding="10, 10, 15, 10">
                                <Image Source="options_icon.png" HeightRequest="18" HorizontalOptions="End" Margin="5, 0, 5, 0" IsVisible="{Binding ShowBanners}">
                                    <Image.GestureRecognizers>
                                        <TapGestureRecognizer Command="{Binding OptionClick}" CommandParameter="{Binding .}"/>
                                    </Image.GestureRecognizers>
                                </Image>
                                <Label Text="{Binding Body}" HorizontalOptions="CenterAndExpand" TextColor="{Binding BodyColor}" FontSize="15" Margin="0, 10, 0, 10"/>
                                <StackLayout x:Name="MessageFooter" Orientation="Horizontal" IsVisible="{Binding ShowBanners}">
                                    <Image x:Name="LikeSource" Source="{Binding LikeImageSource}" HeightRequest="20" HorizontalOptions="StartAndExpand" Margin="0, 0, 10, 0">
                                        <Image.GestureRecognizers>
                                            <TapGestureRecognizer Command="{Binding LikeClick}" CommandParameter="{Binding .}"/>
                                        </Image.GestureRecognizers>
                                    </Image>
                                    <Label Text="{Binding Timestamp}" TextColor="Black" FontSize="10" HorizontalOptions="EndAndExpand"/>
                                </StackLayout>
                            </StackLayout>
                        </StackLayout>
                    </local:PostViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </local:PostListView>
    </StackLayout>
</ContentPage.Content>

My full stack trace is here

Edit:

I added a new TapGesture for a new item and it has the same issue.

3
not sure if this is the issue, but your XAML has a CommandParameter but your actual Command does not - Jason
@Jason I tried removing the CommandParameter, same result. - Dan
see if there is an InnerException value that gives more detail - Jason
There isn't allot of info here so its hard to see what the problem could be. I would suggest changing this line: OptionClick = new Command((sender) => page.DisplayAlert("ok", "ok", "ok")) to OptionClick = new Command(() => page.DisplayAlert("ok", "ok", "ok")) - Christo Nel
@ChristoNel The code still caused the error. :( - Dan

3 Answers

2
votes

There isn't much information we get here, To get the real error try this answer from another Question here.

If that does not work try commenting out your xaml section by section. error could be in <local:PostViewCell> for all we know.

and where is your ViewModel ? it needs a BindableBase

1
votes

Try verify your android native custom renderer, place some breakpoints there.

1
votes

For the command, try running the 'ShowOptionActions' method on the main thread. You can either do that within the ShowOptionActions method itself, or like so:

new Command((sender) =>
    Device.BeginInvokeOnMainThread(() => { 
        ShowOptionActions(message.Id, message.Sender_Id, sender));
    })