.NET MAUI 如何执行嵌套绑定?

问题描述 投票:0回答:1

我想在 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 似乎存在绑定问题,可能与多个数据类型有关?你知道如何解决这个问题吗?

xaml data-binding maui
1个回答
0
投票

这就是绑定的问题。这里有两种方法可以解决。

选项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}}" />

希望有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.