绑定到 ObservableCollection<Tuple<string,string>> 导致错误 XFC0045 绑定:属性 "Item1" 未找到

Binding to ObservableCollection<Tuple<string,string>> results in Error XFC0045 Binding: Property "Item1" not found

我有一个 ObservableCollection>。我想将这个字符串从不同的元组绑定到我的前端。

启动模拟器时,出现如下错误:错误 XFC0045 绑定:属性“Item1”未找到。

.xaml

<ScrollView>
                <CollectionView x:Name="ItemsListView" ItemsSource="{Binding ResultCollection}" SelectionMode="None">
                    <CollectionView.ItemTemplate>
                        <DataTemplate>

                            <StackLayout>
                                <!-- Item 1 = UserAnswer -->
                                <Label Style="{StaticResource SubItem}" Text="{Binding Item1}"/>

                                <!-- Item 2 = CorrectAnswer -->
                                <Label Style="{StaticResource SubItem}" Text="{Binding Item2}"/>
                            </StackLayout>

                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>
            </ScrollView>

ViewModel UserAnswers 和 CorrectAnswers 都是 List.

ResultCollection = new ObservableCollection<Tuple<string, string>>();

for(int i = 0; i < UserAnswers.Count; i++)
{
    ResultCollection.Add(new Tuple<string, string>(UserAnswers[i], CorrectAnswers[i]));
}

谁能帮我在我的 .xaml 中绑定这个元组?

来自 docs

C# tuples, which are backed by System.ValueTuple types, are different from tuples that are represented by System.Tuple types. The main differences are as follows:

  • ValueTuple types are value types. Tuple types are reference types.
  • ValueTuple types are mutable. Tuple types are immutable.
  • Data members of ValueTuple types are fields. Data members of Tuple types are properties.

您只能绑定到 public 属性,因此绑定仅适用于 System.Tuple

您可能在页面前面有一个 x:DataType。鉴于此,要使绑定在 CollectionView 内部起作用,您还需要在 ItemTemplate 或 DataTemplate 上有一个 x:DataType 语句,指定其类型。

但如果绑定数据涉及通用类型 (...<...>),则不能。

这是 XAML 中 x:DataType 声明的限制。

Enhancement Allow generics in x:DataType


修复 #1:

  • 删除 XAML 文件中的所有 x:DataType 语句。

PRO:XF 会在 运行 时弄清楚要做什么。无需进一步更改您的代码即可正常工作。

缺点:如果集合中的项目很多,可能会出现性能问题。


修复#2:

为您的项目定义一个具有属性的自定义 class。在 ItemTemplate 的 DataTemplate 的 x:DataType 中使用 class 名称。

MyTuple.cs:

public class MyTuple : Tuple<string, string>
{
    public MyTuple(string item1, string item2) : base(item1, item2)
    {
    }
}

MyContentPage.xaml:

<ContentPage ...
     xmlns:local="clr-namespace:YourNamespaceHere"   <-- replace YourNamespaceHere
     ...>

...
    <CollectionView ...
        ...
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="local:MyTuple">
        ...

.cs:

public ObservableCollection<MyTuple> ResultCollection { get; set; }

private void Init()
{
    ResultCollection = new ObservableCollection<MyTuple> {
        new MyTuple("a", "abcabc")
    };
}

1.Set 你的 ResultCollection 属性 到 public.

2.Set 您后台代码中的 BindingContext

3.Since 你设置 x:name。您还可以在后台代码中使用类似的代码:ItemsListView.ItemsSource = ResultCollection;

我写了一个小例子供大家参考。

这里是后台代码(xaml代码与你提供的一致):

public partial class MainPage : ContentPage
{
    public ObservableCollection<Tuple<string, string>> ResultCollection { get; set; }//Set public
    public MainPage()
    {
        InitializeComponent();
        ResultCollection = new ObservableCollection<Tuple<string, string>>();

        for (int i = 0; i < 5; i++)
        {
            ResultCollection.Add(new Tuple<string, string>(i.ToString(), i.ToString()));
        }
        BindingContext = this;// Set BindingContext
    }
}