我想在 CarouselView 中使用多个 CollectionView 的绑定。然而,如何才能做到这一点呢?
在视觉上,我正在尝试类似以下的事情:
<--CarouselView: Questions------------------------>
| |
| <Label: QuestionContent /> |
| |
| <--CollectionView: Images----------------> |
| | | |
| <----------------------------------------> |
| |
| <--CollectionView: Answers---------------> |
| | | |
| <----------------------------------------> |
| |
<------------------------------------------------->
我尝试执行以下操作:
模型类如下:
public class Question : ObservableObject
{
public int QuestionType { get; set; }
public string QuestionContent { get; set; }
}
public class Image : ObservableObject
{
public byte[] ImageData { get; set; }
}
public partial class Answer : ObservableObject
{
public string Content { get; set; }
public int? QuestionType { get; set; }
}
ViewModel 将如下所示:
public partial class ViewModel
{
[ObservableProperty]
private ObservableCollection<Question> _questions = new();
[ObservableProperty]
private ObservableCollection<Image> _images = new();
[ObservableProperty]
private ObservableCollection<Answer> _answers = new();
}
视图如下所示:
<!-- Questions Carousel View -->
<CarouselView ItemsSource="{Binding Questions}">
<CarouselView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal"/>
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<Frame BorderColor="{StaticResource NightBlue}">
<Grid>
<!-- QuestionContent -->
<Label Grid.Row="0"
Text="{Binding QuestionContent}"/>
<!-- Images -->
<CollectionView Grid.Row="1"
ItemsSource="{Binding Images}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Image Source="{x:Binding}"
MaximumWidthRequest="200"
MaximumHeightRequest="200" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<!-- Answers -->
<CollectionView Grid.Row="2"
ItemsSource="{Binding Answers">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<!-- Answer Text -->
<Label Grid.Row="0"
Text="{x:Binding Content}"
TextColor="{StaticResource NightBlue}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</Frame>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
但是,这似乎行不通。至少,绑定诊断会发出无法找到绑定属性的警告。我该如何解决这个问题?
更新:
按照建议,我将模型类组合为嵌套表示,如下所示:
public partial class QuestionBlock : ObservableObject
{
public Question question { get; set; }
public ObservableCollection<Image>? images { get; set; }
public ObservableCollection<Answer> answers { get; set; }
public bool? isChecked { get; set; }
}
现在,我遇到了一个不知道如何解决的问题: 我想在相应答案旁边描绘一个单选按钮或复选框,类似于以下内容:
<--CarouselView: Questions--------------------------->
| |
| <Label: QuestionContent /> |
| |
| <--CollectionView: Images----------------> |
| | | |
| <----------------------------------------> |
| |
| <--CollectionView: Answers---------------------> |
| | <Button/CheckBox> <Label: Answer.Content /> | |
| <----------------------------------------------> |
| |
<---------------------------------------------------->
但是,Button/CheckBox 依赖于 Question.QuestionType,而标签则描绘 Answer.Content。该视图具有以下内容:
<!-- Answers -->
<CollectionView
x:DataType="models:QuestionBlock"
ItemsSource="{Binding answers}">
<CollectionView.ItemsLayout>
<LinearItemsLayout
Orientation="Vertical" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Border>
<Grid Padding="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Radio Button for Standard Questions -->
<RadioButton Grid.Column="0"
x:DataType="models:QuestionBlock"
GroupName="radioButtonGroup"
VerticalOptions="Center"
IsChecked="{Binding isChecked, Mode=TwoWay}"
IsVisible="{Binding question.QuestionType, Converter={StaticResource QuestionTypeIsStandardToBooleanConverter}}" />
<!-- Check Box for Multiple Choice Questions -->
<CheckBox
Grid.Column="0"
x:DataType="models:QuestionBlock"
VerticalOptions="Center"
IsChecked="{Binding isChecked, Mode=TwoWay}"
IsVisible="{Binding question.QuestionType, Converter={StaticResource QuestionTypeIsMultipleChoiceToBooleanConverter}}"
/>
<!-- Answer Text -->
<Label Grid.Column="1"
x:DataType="models:Answer"
VerticalOptions="Center"
Text="{Binding Content}"
TextColor="{StaticResource NightBlue}" />
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
如何解决这个问题? IsVisible 似乎存在绑定问题,可能与多个数据类型有关?你知道如何解决这个问题吗?
这就是绑定的问题。这里有两种方法可以解决。
选项1,使用相对绑定。
CheckBox
和 RadioButton
都位于 CollectionView
的数据模板中。默认的 BindingContext 是答案集合中的每个答案。因此,我们应该使用相对绑定来查找QuestionBlock,它是祖先的 BindingContext。您可以在此处查看文档,绑定到祖先。请尝试以下代码来获取 IsVisible
属性
IsVisible="{Binding question.QuestionType,Source={RelativeSource AncestorType={x:Type models:QuestionBlock}}}"
顺便说一下,设置
x:DataType
不能设置BindingContext。
选项2,使用
x:Reference
,
我们将Frame的名称设置为“myframe”。因为这个
Frame
的BindingContext是QuestionBlock,
<CarouselView.ItemTemplate>
<DataTemplate>
<Frame x:Name="myframe">
<Grid>
...
我们访问Frame的BindingContext使用
x:Reference
,
IsVisible="{Binding BindingContext.question.QuestionType,Source={x:Reference myframe}}" />
希望有帮助!