即使内容和代码最少,扩展 viewcell 的自定义控件也会引发 System.InvalidCastException

Posted

技术标签:

【中文标题】即使内容和代码最少,扩展 viewcell 的自定义控件也会引发 System.InvalidCastException【英文标题】:Custom control extending viewcell throws System.InvalidCastException even with minimal content and code 【发布时间】:2021-06-03 16:46:45 【问题描述】:

我正在尝试为我的 Xamarin 应用创建我的第一个自定义控件,但遇到了错误,System.InvalidCastException:“指定的转换无效。”

我已经从这个自定义控件中删除了所有内容,但它仍然无法正常工作。我知道它与该控件有关,因为当我删除它并用标签替换它时,它可以工作。代码如下。请注意,我已经注释掉了几乎所有额外的内容,但错误仍然存​​在。

相关视图单元的代码隐藏,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();

        


    

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>

正在使用的数据类型,虽然它在仅使用测试标签时不会引起问题:

    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");
        

    

包含它的内容页面

<?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>

【问题讨论】:

【参考方案1】:

因为您不能在DataTemplate 中使用ViewCell 元素,例如ListView

CarouselView没有单元格的概念。而是使用数据模板来定义列表中每一项数据的外观。

这就是为什么你可以直接使用 Label 元素但不能使用 ViewCell 或其派生类的原因。

您可以让您的自定义类扩展 StackLayoutContentView 以满足您的需要。

【讨论】:

谢谢,这很有道理。

以上是关于即使内容和代码最少,扩展 viewcell 的自定义控件也会引发 System.InvalidCastException的主要内容,如果未能解决你的问题,请参考以下文章

如何在Xamarin viewcell或Grid或某处显示默认文件扩展名图标?

如何在VS代码的SonarQube扩展中自定义和关闭声纳规则

代码演示Mybatis-Generator 扩展自定义生成

如何在 Xamarin Forms 的可重用 ViewCell 中绑定命令?

Xamarin.UWP 自定义 ViewCell 存在绑定问题

在 viewCell,UIViewCollection 中使按钮可点击