XAML ContentControl数据绑定无法工作

3
我可以帮您翻译成中文。这段内容涉及数据模板和内容控件的问题,具体情况非常特殊。
XAML页面:
<Page
    x:Class="Questionnaires.QuestionPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Questionnaires"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:selectors="using:Questionnaires.TemplateSelectors"
    xmlns:interop="using:Windows.UI.Xaml.Interop"
    mc:Ignorable="d">

    <Page.Resources>
        <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
        <selectors:QuestionTypeItemTemplateSelector x:Key="QuestionTypeSelector" />
        <selectors:AnswerTypeItemTemplateSelector x:Key="AnswerTypeSelector"/>

        <DataTemplate x:Key="SingleSelectQuestionItemTemplate">
            <Grid Margin="10">
                <RadioButton HorizontalAlignment="Left" VerticalAlignment="Center" 
                             IsChecked="{Binding IsChecked, Mode=TwoWay}"
                             Width="600" Height="Auto" GroupName="groupName">
                    <RadioButton.Content>
                        <TextBlock Text="{Binding Text}" TextWrapping="Wrap"/>
                    </RadioButton.Content>
                </RadioButton>
            </Grid>
        </DataTemplate>
        <DataTemplate x:Key="FreeQuestionItemTemplate">
            <Grid Margin="10">

                <ContentPresenter Content="{Binding}" ContentTemplateSelector="{StaticResource AnswerTypeSelector}" />


                <!--
                <GridView ItemsSource="{Binding}" SelectionMode="None">

                    <GridView.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapGrid Orientation="Horizontal" />
                        </ItemsPanelTemplate>
                    </GridView.ItemsPanel>
                </GridView>
                -->
            </Grid>
        </DataTemplate>
        <DataTemplate x:Key="MultiSelectQuestionItemTemplate">
            <Grid Margin="10">
                <CheckBox HorizontalAlignment="Left" VerticalAlignment="Center"
                          IsChecked="{Binding IsChecked, Mode=TwoWay}" Width="600">
                    <CheckBox.Content>
                        <TextBlock Text="{Binding Text}" TextWrapping="Wrap"/>
                    </CheckBox.Content>    
                </CheckBox>
            </Grid>
        </DataTemplate>

        <DataTemplate x:Key="LabelAnswerItemTemplate">
        </DataTemplate>

        <DataTemplate x:Key="TextAreaAnswerItemTemplate">
        </DataTemplate>

        <DataTemplate x:Key="TextFieldAnswerItemTemplate">
        </DataTemplate>

        <DataTemplate x:Key="DateAnswerItemTemplate">
        </DataTemplate>

        <DataTemplate x:Key="SliderAnswerItemTemplate">
            <Grid Margin="10">
                <Slider Width="600" Minimum="0" Maximum="100" Value="25" />
            </Grid>
        </DataTemplate>

    </Page.Resources>

    <Grid>
        <Grid.Background>
            <ImageBrush Stretch="None" ImageSource="Assets/IS_Bol_White.png"/>
        </Grid.Background>
        <Grid.ChildrenTransitions>
            <TransitionCollection>
                <EntranceThemeTransition/>
            </TransitionCollection>
        </Grid.ChildrenTransitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="108*"/>
            <RowDefinition Height="60"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="120"/>
            <ColumnDefinition Width="235*"/>
            <ColumnDefinition Width="1011*"/>
        </Grid.ColumnDefinitions>
        <TextBlock x:Name="pageTitle" Text="{Binding Path=Assignment.Definition.Name}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                        IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40" Grid.ColumnSpan="2" FontSize="48"/>

        <Image Grid.Column="2" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,30,0" Width="252" Height="71" Source="ms-appx:///Assets\innovationstudio.png" />

        <Grid Grid.Column="2" Grid.Row="1" Margin="3,0,358,0" Width="650">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <ProgressBar Grid.Row ="0" Maximum="1" Value="{Binding Progress}" IsIndeterminate="False" Grid.ColumnSpan="2" Foreground="Black"/>
            <TextBlock Grid.Row="1" Grid.ColumnSpan="2" Margin="10 20" TextAlignment="Left" HorizontalAlignment="Left" Style="{StaticResource SubheaderTextBlockStyle}"
                       Text="{Binding CurrentQuestion.Text}" />

        </Grid>

        <GridView Grid.Column="2" Grid.Row="2" ItemsSource="{Binding CurrentQuestion.PossibleAnswers}" 
                  ItemTemplateSelector="{StaticResource QuestionTypeSelector}" SelectionMode="None">
            <GridView.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapGrid Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </GridView.ItemsPanel>
        </GridView>

        <Grid Grid.Column="2" Grid.Row="3" Margin="3,0,358,0" Width="650">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button x:Name="btn_Previous" Grid.Column="0" HorizontalAlignment="Left" Content="Vorige" Height="59" Width="175" IsEnabled="{Binding IsPreviousButtonEnabled}" Click="btnPrevious_Click"/>
            <Button x:Name="btn_Next" Grid.Column="1" HorizontalAlignment="Right" Content="Volgende" Height="59" Width="175" IsEnabled="{Binding IsNextButtonEnabled}" Click="btnNext_Click"/>
        </Grid>
    </Grid>
</Page>

我使用ItemTemplateSelector来指定问题类型。QuestionType在PossibleAnswer对象中定义。我的ItemTemplateSelector如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Questionnaires.Models;
using Questionnaires.ViewModels;

namespace Questionnaires.TemplateSelectors
{
    public class QuestionTypeItemTemplateSelector : DataTemplateSelector
    {
        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
        {
            switch (((PossibleAnswer)(item)).QuestionType)
            {
                case "FREE":
                    return
                        ((Page) ((Frame) Window.Current.Content).Content).Resources["FreeQuestionItemTemplate"] 
                            as
                            Windows.UI.Xaml.DataTemplate;
                case "SINGLE_SELECT":
                    return
                        ((Page) ((Frame) Window.Current.Content).Content).Resources["SingleSelectQuestionItemTemplate"]
                            as
                            Windows.UI.Xaml.DataTemplate;
                case "MULTI_SELECT":
                    return
                        ((Page) ((Frame) Window.Current.Content).Content).Resources["MultiSelectQuestionItemTemplate"]
                            as Windows.UI.Xaml.DataTemplate;
                case "DROPDOWN":
                    return
                        ((Page) ((Frame) Window.Current.Content).Content).Resources["DropdownQuestionItemTemplate"]
                            as Windows.UI.Xaml.DataTemplate;
                default:
                    return null;
            }
        }
    }
}

这样我可以指定在我的页面上显示哪个数据模板。我目前正在处理免费问题,因此现在我只谈论一个特定的模板。我的XAML上的模板如下所示:
<Page.Resources>
    <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
    <selectors:QuestionTypeItemTemplateSelector x:Key="QuestionTypeSelector" />
    <selectors:AnswerTypeItemTemplateSelector x:Key="AnswerTypeSelector"/>

    <DataTemplate x:Key="FreeQuestionItemTemplate">
        <Grid Margin="10">
            <ContentControl Content="{Binding}" ContentTemplateSelector="{StaticResource AnswerTypeSelector}" />
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="SliderAnswerItemTemplate">
        <Grid Margin="10">
            <Slider Width="600" Minimum="0" Maximum="100" Value="25" />
        </Grid>
    </DataTemplate>
</Page.Resources>

为了让事情更清楚一些:QuestionType和PossibleAnswerType之间存在区别。 QuestionType可以是:

FREE SINGLE_SELECT MULTI_SELECT DROPDOWN TABLE

PossibleAnswerType可以是:

LABEL TEXT_AREA TEXT_FIELD DATE SLIDER

我试图在FreeQuestionTemplate中获取PossibleAnswer的PossibleAnswerType。 我使用ContentControl来实现这一点,但我的PossibleAnswer绑定似乎不起作用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Questionnaires.Models;

namespace Questionnaires.TemplateSelectors
{
    public class AnswerTypeItemTemplateSelector : DataTemplateSelector
    {
        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
        {
            switch (((PossibleAnswer) (item)).PossibleAnswerType)
            {
                case "LABEL":
                    return
                       ((Page)((Frame)Window.Current.Content).Content).Resources["LabelAnswerItemTemplate"]
                           as
                           Windows.UI.Xaml.DataTemplate;
                case "TEXT_AREA":
                    return
                       ((Page)((Frame)Window.Current.Content).Content).Resources["TextAreaAnswerItemTemplate"]
                           as
                           Windows.UI.Xaml.DataTemplate;
                case "TEXT_FIELD":
                    return
                       ((Page)((Frame)Window.Current.Content).Content).Resources["TextFieldAnswerItemTemplate"]
                           as
                           Windows.UI.Xaml.DataTemplate;
                case "DATE":
                    return
                       ((Page)((Frame)Window.Current.Content).Content).Resources["DateAnswerItemTemplate"]
                           as
                           Windows.UI.Xaml.DataTemplate;
                case "SLIDER":
                    return
                       ((Page)((Frame)Window.Current.Content).Content).Resources["SliderAnswerItemTemplate"]
                           as
                           Windows.UI.Xaml.DataTemplate;
                default:
                    return null;
            }
        }
    }
}

在我的AnswerTypeItemTemplateSelector中,item对象始终为null。有人能给我一些关于如何解决这个问题的建议吗?
谢谢!

下次在发布问题之前,请先仔细阅读您的问题……您缺少了一部分代码。我已经重新格式化它,现在可以看到了。 - Sheridan
你尝试过简单的 null 检查吗?if (object == null) return; - Sheridan
问题在于我的项目应该是一个PossibleAnswer :) 这里的空值检查并不重要。此时项目应该包含数据。 - TurboTheunis
你是说它总是null吗? - Sheridan
好的,现在我终于明白了你的问题。 :) 请问您能展示一下你设置页面DataContext和使用FreeQuestionItemTemplate的XAML代码吗? - Sheridan
显示剩余2条评论
1个回答

0

好的,看了你的新代码后,我想我已经找出了问题所在。你的AnswerTypeItemTemplateSelector被用在了你的FreeQuestionItemTemplate DataTemplate中,而这个模板又被用在了你的QuestionTypeItemTemplateSelector中。除非你遗漏了一些XAML代码,否则似乎你没有在任何地方使用你的QuestionTypeItemTemplateSelector,因此这些代码都没有被“插入”到程序中。


更新 >>>

为了使任何绑定生效,您必须PageDataContext设置为某个有意义的值。 DataContext告诉UI中的元素在哪里查找其数据绑定的值。如果不设置DataContext,UI元素将无法访问任何数据(除非在XAML中声明了一些数据,但让我们不要混淆这个问题)。请参阅《WPF中的DataContext》CodeProject文章以获取更多信息。


我正在使用我的QuestionTypeItemTemplateSelector在我的xaml底部的gridview中:ItemTemplateSelector = "{StaticResource QuestionTypeSelector}" - TurboTheunis
啊...原来你是...我一直在寻找QuestionTypeItemTemplateSelector...我会再仔细看的。你从未回答过关于你的DataContext的问题...我没看到你在任何地方设置它。请展示一下你如何设置这个必要的属性。 - Sheridan
你的意思是我需要在ContentPresenter上设置DataContext吗?还是应该在哪个标签上设置? - TurboTheunis
好的,我已将我的ContentPresenter更改为以下内容:<ContentPresenter ContentTemplateSelector="{StaticResource AnswerTypeSelector}" DataContext="{Binding}" /> 但是在AnswerTypeSelector中,项目对象仍然返回“null”。 - TurboTheunis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接