Button inside listview clicked error: Exception thrown: 'System.InvalidCastException'.

antoniojrantoniojr BRMember ✭✭
edited June 2016 in Xamarin.Forms

I have a button inside a listview, but clicking the button returns the error:
Exception thrown: 'System.InvalidCastException'. **
**In line:
((ContentPage)((ListView)((StackLayout)((StackLayout)b.Parent).Parent).Parent).Parent).DisplayAlert("Clicked", item.Title.ToString() + " button was clicked", "OK");

What is wrong?

public class ListViewButton : ContentPage
{
    public class ListItem
    {
        public string Source { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public string Price { get; set; }
    }
    public ListViewButton()
    {
        var listView = new ListView();
        listView.ItemsSource = new ListItem[] {
            new ListItem {Title = "First", Description="1st item", Price="$100.00"},
            new ListItem {Title = "Second", Description="2nd item", Price="$200.00"},
            new ListItem {Title = "Third", Description="3rd item", Price="$300.00"}
        };
        listView.RowHeight = 100;   
        listView.BackgroundColor = Color.Black;
        listView.HasUnevenRows = true;
        listView.ItemTemplate = new DataTemplate(typeof(ListItemCell));
        Content = listView;

        listView.ItemTapped += async (sender, e) =>
        {
            ListItem item = (ListItem)e.Item;
            await DisplayAlert("Tapped", item.Title.ToString() + " was selected.", "OK");
            ((ListView)sender).SelectedItem = null;
        };

        this.Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);
    }


    class ListItemCell : ViewCell
    {
        public ListItemCell()
        {

            Label titleLabel = new Label
            {
                HorizontalOptions = LayoutOptions.Start,
                FontSize = 20,
                FontAttributes = Xamarin.Forms.FontAttributes.Bold,
                TextColor = Color.White
            };
            titleLabel.SetBinding(Label.TextProperty, "Title");

            Label descLabel = new Label
            {
                HorizontalOptions = LayoutOptions.Start,
                FontSize = 12,
                TextColor = Color.White
            };
            descLabel.SetBinding(Label.TextProperty, "Description");


            StackLayout viewLayoutItem = new StackLayout()
            {
                HorizontalOptions = LayoutOptions.Start,
                Orientation = StackOrientation.Vertical,
                WidthRequest = 120,
                Children = { titleLabel, descLabel }
            };

            Label priceLabel = new Label
            {
                HorizontalOptions = LayoutOptions.Center,
                FontSize = 25,
                TextColor = Color.Aqua
            };
            priceLabel.SetBinding(Label.TextProperty, "Price");

            var button = new Button //ListButton // Android workaround
            {
                Text = "Buy Now",
                BackgroundColor = Color.Teal,
                HorizontalOptions = LayoutOptions.EndAndExpand
            };
            string titulo;
            button.SetBinding(Button.CommandParameterProperty, new Binding("."));
            button.Clicked += (sender, e) =>
            {
                var b = (Button)sender;
                var item = (ListItem)b.CommandParameter;
                ((ContentPage)((ListView)((StackLayout)((StackLayout)b.Parent).Parent).Parent).Parent).DisplayAlert("Clicked", item.Title.ToString() + " button was clicked", "OK");

            };

            StackLayout viewButton = new StackLayout()
            {
                HorizontalOptions = LayoutOptions.EndAndExpand,
                Orientation = StackOrientation.Horizontal,
                WidthRequest = 260,
                Children = { priceLabel, button }
            };


            StackLayout viewLayout = new StackLayout()
            {
                HorizontalOptions = LayoutOptions.StartAndExpand,
                Orientation = StackOrientation.Horizontal,
                Padding = new Thickness(5, 10, 5, 15),
                Children = { viewLayoutItem, viewButton }
            };

            View = viewLayout;
        }

    }

}

Posts

  • AdamPAdamP AUUniversity ✭✭✭✭✭

    @antoniojr - In this line

    ((ContentPage)((ListView)((StackLayout)((StackLayout)b.Parent).Parent).Parent).Parent).DisplayAlert("Clicked", item.Title.ToString() + " button was clicked", "OK");

    One of your casts is not correct. Its a bit hard to tell without debugging, but if you breakpoint this line, then check each parent.

    However this is generally not the best way to achieve what you want.

    Instead put this in your ContentPage

    public static ContentPage Main { get; set; }
    
    public ListViewButton()
    {
        // Add this into your already existing constructor
        Main = this;
    }
    

    Then do

    ListViewButton.Main.DisplayAlert("Clicked", item.Title.ToString() + " button was clicked", "OK");

    Ideally if you have a navigation page or something above you would static the NavigationPage or hold a reference and call that directly, rather than the ContentPage.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    You can try with Application.Current.MainPage.DisplayAlert

  • antoniojrantoniojr BRMember ✭✭

    Alessandro and Adam, thank you for your help. The two worked!

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Yes, but mine is better ahahah

  • antoniojrantoniojr BRMember ✭✭

    hahahahahahaha

  • antoniojrantoniojr BRMember ✭✭

    Now the error by clicking the button :neutral:

    file: App.g.i.cs

    if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION

           UnhandledException += (sender, e) =>
           {
               if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break(); //error in this line
           };
    

    endif

       }
    

    Message: "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
    Native View: Unable to evaluation the expression.Operation not suported. Unkdown erro0x80070057
    Stacktrace:
    " at Windows.UI.Popups.MessageDialog.ShowAsync()\r\n at Xamarin.Forms.Platform.WinRT.Platform.d__55.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.AsyncMethodBuilderCore.b__3(Object state)\r\n at System.Threading.WinRTSynchronizationContext.Invoker.InvokeCore()"

    What is going on?

  • AdamPAdamP AUUniversity ✭✭✭✭✭
    edited June 2016

    @antoniojr - DisplayAlert needs to be called on the Main UI Thread (WinRT/UWP especially) but a button is called on the UI Thread so I am not seeing how this error is occurring, unless you moved the code elsewhere.

    Try

    Device.BeginInvokeOnMainThread(async () =>
    {
        .. display alert here ..
    });
    
  • antoniojrantoniojr BRMember ✭✭
    edited June 2016

    @AdamP
    OK thank you!

    the displayalert would be to see if you are returning the button event properly. At the debug item.Title receives the value correctly in clicked, but would like to assign this value to a line label in my ContentPage.
    How would I do?

Sign In or Register to comment.