Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid Cast Exception with BindablePicker #27

Open
ghost opened this issue Jan 23, 2017 · 8 comments
Open

Invalid Cast Exception with BindablePicker #27

ghost opened this issue Jan 23, 2017 · 8 comments

Comments

@ghost
Copy link

ghost commented Jan 23, 2017

I have used FreshEssentials BindablePicker in other projects fine, but am having a very strange problem with a particular Page/PageModel.

I have stripped the Page and PageModel right down to the following:
Page:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage x:Class="Manager.Pages.Config.RemoteConnectionsPage"
             xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:fe="clr-namespace:FreshEssentials;assembly=FreshEssentials">
    <ContentPage.Content>
        <StackLayout Orientation="Vertical">
            <Label HorizontalOptions="CenterAndExpand" Text="Main Page" />
            <fe:BindablePicker DisplayProperty="Name" ItemsSource="{Binding Environments}" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

PageModel:

using System.Collections.Generic;
using FreshMvvm;
using PropertyChanged;

namespace Manager.PageModels.Config
{
    [ImplementPropertyChanged]
    public class RemoteConnectionsPageModel : FreshBasePageModel
    {
        public enum Environment
        {
            Live,
            Test,
            Third
        }

        public class EnvironmentPickerItem
        {
            public string Name {
                get {
                    return Env.ToString ();
                }
            }

            public Environment Env {
                get;
                set;
            }
        }
        public RemoteConnectionsPageModel ()
        {
            List<EnvironmentPickerItem> _Environments;
            _Environments = new List<EnvironmentPickerItem> ();
            _Environments.Add (new EnvironmentPickerItem () { Env = Environment.Live });
            _Environments.Add (new EnvironmentPickerItem () { Env = Environment.Test });
            _Environments.Add (new EnvironmentPickerItem () { Env = Environment.Third });
            this.Environments = _Environments;
        }

        public List<EnvironmentPickerItem> Environments {
            get;
            set;
        }
    }
}

The problem is when I run the application, I get the exception below (full stack trace truncated):

System.InvalidCastException: Specified cast is not valid.
at FreshEssentials.Droid.BindablePickerRendererDroid.OnElementChanged (Xamarin.Forms.Platform.Android.ElementChangedEventArgs1[TElement] e) [0x00031] in C:\Users\Michael\Documents\FreshEssentials\src\Droid\Renderers\BindablePickerRendererDroid.cs:46 at Xamarin.Forms.Platform.Android.VisualElementRenderer1[TElement].SetElement (TElement element) [0x000f4] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:190
at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00027] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:131

Looking at the source for the BindablePickerRendererDroid from the FreshEssentials repository, it appears to be the line:

((ObservableCollection<string>)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;

in this method.

protected override void OnElementChanged(ElementChangedEventArgs<BindablePicker> e)
        {
            if (e.OldElement != null)
                ((ObservableCollection<string>)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;

            if (e.NewElement != null)
            {
                ((ObservableCollection<string>)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
                if (Control == null)
                {
                    var button = new AButton(Context) { Focusable = false, Clickable = true, Tag = this, Text = e.NewElement.Title };
                    button.SetOnClickListener(PickerListener.Instance);
                    SetNativeControl(button);
                }
                UpdatePicker();
            }

            base.OnElementChanged(e);
        }

The strange thing is that taking the above exact code into a brand new project works fine. I have checked versions of FreshEssentials and FreshMVVM, and they're identical between the working and non-working projects.

Anyone come across this, and/or any thoughts?

Full Xamarin Studio and other version info below:

=== Xamarin Studio Community ===

Version 6.1.4 (build 1)
Installation UUID: 462e6ba8-9cb7-4b87-acc8-9dfb0ab2c6f7
Runtime:
Mono 4.6.2 (mono-4.6.0-branch/ac9e222) (64-bit)
GTK+ 2.24.23 (Raleigh theme)

Package version: 406020016

=== NuGet ===

Version: 3.4.3.0

=== Xamarin.Profiler ===

Version: 0.33.2
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

=== Xamarin.Android ===

Version: 7.0.2.42 (Xamarin Studio Community)
Android SDK: /Users/jameslavery/Library/Developer/Xamarin/android-sdk-macosx
Supported Android versions:
2.3 (API level 10)
4.0.3 (API level 15)
4.1 (API level 16)
4.3 (API level 18)
4.4 (API level 19)
5.0 (API level 21)
5.1 (API level 22)
6.0 (API level 23)

SDK Tools Version: 24.4.1
SDK Platform Tools Version: 23.1
SDK Build Tools Version: 23.0.1

Java SDK: /usr
java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)

Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

=== Xamarin Android Player ===

Version: 0.6.5
Location: /Applications/Xamarin Android Player.app

=== Apple Developer Tools ===

Xcode 8.0 (11246)
Build 8A218a

=== Xamarin.iOS ===

Version: 10.3.1.8 (Xamarin Studio Community)
Hash: 7beaef4
Branch: cycle8-xi
Build date: 2016-12-20 02:58:14-0500

=== Xamarin.Mac ===

Version: 2.10.0.120 (Xamarin Studio Community)

=== Build Information ===

Release ID: 601040001
Git revision: e606823f2dd01b4552216c013b597a73bec2068f
Build date: 2017-01-10 17:28:57-05
Xamarin addins: c92d0626d347aaa02839689eaac2961d24c9f446
Build lane: monodevelop-lion-cycle8

=== Operating System ===

Mac OS X 10.11.6
Darwin Jamess-MacBook-Pro.local 15.6.0 Darwin Kernel Version 15.6.0
Thu Jun 23 18:25:34 PDT 2016
root:xnu-3248.60.10~1/RELEASE_X86_64 x86_64

=== Enabled user installed addins ===

StyleCop Support 1.0.1.9
Gorilla Player 0.9.1.2
XamlStyler 1.0.2

@jessejiang0214
Copy link
Contributor

jessejiang0214 commented Jan 25, 2017

I have no idea,

For this line, I copied these code from Xamarin.Forms.
((ObservableCollection)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;

NewElement.Items is Picker.Items. BindablePicker inherit from Picker

Would you please link FreshEssentials source code into your project? So that we can know what's the exception it throw.

@ghost
Copy link
Author

ghost commented Jan 25, 2017

Thanks for looking at it. Yes the next step is going to have to be linking the source so we can debug the problem.

@rdaniel0
Copy link

rdaniel0 commented Mar 30, 2017

I've pulled the source directly to debug it because I was getting the same InvalidCastException.
It's the same line, and it's because e.NewElement.Items is for some reason unable to be cast to ObservableCollection<string>

I have only observed this error on android support verison 25.1.1

I'm going to try and fix it soon (as I need it in my current project asap) and if it works for me, I'll provide a pull request.

@veeprox
Copy link

veeprox commented Mar 30, 2017

Your binding source MUST be castable to IList or this class will throw an error. My issue is the cast to an IList here on line 99 in BindablePicker.cs;

picker.ItemsSource = (IList) newValue

I have a dictionary of items I wanna show in the picker. I was trying to bind ItemsSource to MyDictionary.Values which is a ValueCollection and isn't castable to IList.

MyDictionary.Values.ToList() fixed my issue.

@ManuelArroz
Copy link

View

[https://developer.xamarin.com/guides/xamarin-forms/user-interface/picker/]

This is the recommended technique, which was introduced in Xamarin.Forms 2.3.4.

And
[https://developer.xamarin.com/guides/xamarin-forms/user-interface/picker/populating-itemssource/]

@acaliaro
Copy link

I have the same problem... before (using Xamarin Studio) no problem with your BindablePicker. Today (uninstalled Xamarin Studio, installe Visual Studio for Mac), the exception.

Changed BindablePicker with XF 2.4.3 Picker, it works

@micuentadecasa
Copy link

I had the same problem, changed code to the current code for the BindablePickerRendererDroid.cs and it works now

@learsixela
Copy link

Hi, can you help me, I'm trying to run the example on android from VS to Mac and it does not work, do not drop the screen with the "Change source of Picker" button, it throws the same exception, I thank you.
(In IOs it works),sorry for my english, it's pretty bad

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants