Peter F
Peter F

Reputation: 435

Custom control extending viewcell throws System.InvalidCastException even with minimal content and code

I am trying to create my first custom control for my Xamarin app, and am encountering an error, System.InvalidCastException: 'Specified cast is not valid.'

I have removed about everything from this custom control and it still isn't working. I know it has to do with that control because when I remove it, and replace it with just a label, it works. Code below. Note that I have commented out almost everything extra and the error still occurs.

The codebehind for the viewcell in question, DFilterView:

    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class DFilterView : ViewCell
    {

        //public static readonly BindableProperty AnswerChosenProperty = BindableProperty.Create("AnswerChosen", typeof(int), typeof(DFilterView), 0);

        //public int AnswerChosen
        //{
        //    get { return (int)GetValue(AnswerChosenProperty); }
        //    set { SetValue(AnswerChosenProperty, value); }
        //}

        public DFilterView()
        {
            InitializeComponent();

        }


    }

The DFilterView XAML

<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Finder.Controls.DFilterView">
    <ViewCell.View>
        <Grid BackgroundColor="Black">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <!--<Label Text="{Binding Question}" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="7" HorizontalOptions="CenterAndExpand" FontSize="30"></Label>
            <Button Text="{Binding Answer1}" Command="{Binding AnswerCommand1}" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="3"></Button>
            <Button Text="{Binding Answer2}" Command="{Binding AnswerCommand2}" Grid.Column="4" Grid.Row="3" Grid.ColumnSpan="3"></Button>
            <Button Text="{Binding Answer3}" Command="{Binding AnswerCommand3}" Grid.Column="2" Grid.Row="1" Grid.ColumnSpan="3"></Button>-->
        </Grid>
    </ViewCell.View>
</ViewCell>

The datatype being used, although it does not cause problems when just using the test label:

    public class DMenuItem_Filter : DMenuItem
    {
        private int answerSelected;
        public int AnswerSelected { get { return answerSelected; } set { answerSelected = value; } }

        private string question;
        public string Question { get { return question; } set { question = value; } }

        private string answer1;
        public string Answer1 { get { return answer1; } set { answer1 = value; } }

        private string answer2;
        public string Answer2 { get { return answer2; } set { answer2 = value; } }

        private string answer3;
        public string Answer3 { get { return answer3; } set { answer3 = value; } }

        public Command AnswerCommand1 { get; set; }
        public Command AnswerCommand2 { get; set; }
        public Command AnswerCommand3 { get; set; }

        public DMenuItem_Filter(string Q, string a1, string a2, string a3)
        {
            answerSelected = 0;
            question = Q;
            answer1 = a1;
            answer2 = a2;
            answer3 = a3;
            AnswerCommand1 = new Command(async () => await ExecuteAnswerCommand1());
            AnswerCommand2 = new Command(async () => await ExecuteAnswerCommand2());
            AnswerCommand3 = new Command(async () => await ExecuteAnswerCommand3());
        }

        async Task ExecuteAnswerCommand1()
        {
            answerSelected = 1;
            OnPropertyChanged("AnswerSelected");
        }

        async Task ExecuteAnswerCommand2()
        {
            answerSelected = 2;
            OnPropertyChanged("AnswerSelected");
        }

        async Task ExecuteAnswerCommand3()
        {
            answerSelected = 3;
            OnPropertyChanged("AnswerSelected");
        }

    }

The content page which holds it

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="Finder.Views.DV_FinderParty_Filter"
             xmlns:m="clr-namespace:Finder.MenuItems"
             xmlns:v="clr-namespace:Finder.Views"
             xmlns:comp="clr-namespace:Finder.Controls"
             Title="My Meals"
             ControlTemplate="{StaticResource SearchNextTemplate}"
             x:Name="FinderParty_Filter">


    
    <ContentPage.Resources>
        <ResourceDictionary>
            <Color x:Key="Primary">#2196F3</Color>
            <Color x:Key="Accent">#96d1ff</Color>
            <Color x:Key="LightTextColor">#999999</Color>
        </ResourceDictionary>
    </ContentPage.Resources>



    <Frame HorizontalOptions="FillAndExpand"
           VerticalOptions="FillAndExpand"
           BackgroundColor="Aqua">
        <StackLayout>
            <CarouselView ItemsSource="{Binding TheFilters}" x:Name="TheFilterCarousel"
                       HorizontalOptions="FillAndExpand"
                      VerticalOptions="FillAndExpand"
                      BackgroundColor="Indigo">
                <CarouselView.ItemTemplate>
                    <DataTemplate x:DataType="m:DMenuItem_Filter">
                        <!--<Label Text="Test"></Label>-->
                        <comp:DFilterView ></comp:DFilterView>
                    </DataTemplate>
                </CarouselView.ItemTemplate>
                <!--AnswerChosen="{Binding Source={x:Reference FinderParty_Filter}, Path=BindingContext.AnswerChosen}"-->
            </CarouselView>
        </StackLayout>
         
    </Frame>


</ContentPage>

Upvotes: 1

Views: 68

Answers (1)

Leo Zhu
Leo Zhu

Reputation: 14956

Because you couldn't use ViewCell elements in the DataTemplate like ListView.

CarouselView has no concept of cells.Instead, a data template is used to define the appearance of each item of data in the list.

So that's why you could use Label element directly but could not use ViewCell or its derived class.

You could let your custom class extends StackLayout or ContentView to suit your need.

Upvotes: 1

Related Questions