Loading Different DataTemplate for each item in Li

2019-07-15 13:39发布

I am trying to create a learn application and I would like to load data template for based on Question type as explained below.

     If Question Type is TYPE1

     load InstructionTemplate_Type1.xaml
     load ChoiceTemplate_Type1.xaml
     load QuestionTemplate_Type1.xaml

     If Question Type is TYPE2

     load InstructionTemplate_Type2.xaml
     load ChoiceTemplate_Type2.xaml
     load QuestionTemplate_Type2.xaml

     If Question Type is TYPE3

     load InstructionTemplate_Type3.xaml
     load ChoiceTemplate_Type3.xaml
     load QuestionTemplate_Type3.xaml

     else

     load InstructionTemplate_Type3.xaml
     load ChoiceTemplate_Type3.xaml
     load QuestionTemplate_Type3.xaml

and the my page should look like...

learn page

Can Someone help me how to do this.

I am using the code from my previous post

Nested ObservableCollection data binding in WPF

and the xaml is ...

    <learn:SelectedItemIsCorrectToBooleanConverter x:Key="SelectedCheckedToBoolean" />

    <Style x:Key="ChoiceRadioButtonStyle" TargetType="{x:Type RadioButton}" BasedOn="{StaticResource {x:Type RadioButton}}">
        <Style.Triggers>
            <DataTrigger Value="True">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource SelectedCheckedToBoolean}">
                        <Binding Path="IsCorrect" />
                        <Binding RelativeSource="{RelativeSource Self}" Path="IsChecked" />
                    </MultiBinding>
                </DataTrigger.Binding>
                <Setter Property="Background" Value="Green"></Setter>
            </DataTrigger>
            <DataTrigger Value="False">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource SelectedCheckedToBoolean}">
                        <Binding Path="IsCorrect" />
                        <Binding RelativeSource="{RelativeSource Self}" Path="IsChecked" />
                    </MultiBinding>
                </DataTrigger.Binding>
                <Setter Property="Background" Value="Red"></Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <DataTemplate x:Key="InstructionTemplate" DataType="{x:Type learn:Question}">
        <TextBlock Text="{Binding Path=Instruction}" />
    </DataTemplate>

     <DataTemplate x:Key="ChoiceTemplate" DataType="{x:Type learn:Choice}">
                        <RadioButton Content="{Binding Path=Name}" IsChecked="{Binding RelativeSource=   {RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Margin="10 1" 
                                     Style="{StaticResource ChoiceRadioButtonStyle}" />
                    </DataTemplate>

    <DataTemplate x:Key="QuestionTemplate" DataType="{x:Type learn:Question}">
        <StackPanel Margin="10 0">
            <TextBlock Text="{Binding Path=Name}" />
            <ListBox ItemsSource="{Binding Path=Choices}" SelectedItem="{Binding Path=SelectedChoice}" HorizontalAlignment="Stretch" ItemTemplate="ChoiceTemplate">

            </ListBox>
        </StackPanel>
    </DataTemplate>
</Window.Resources>

<DockPanel>
    <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom">
        <Button Content="Select Question 3 choice 3" Click="ButtonBase_OnClick" />
    </StackPanel>
    <ItemsControl ItemsSource="{Binding Path=Questions}">
        <ItemsControl.ItemTemplateSelector>
            <learn:QuestionTemplateSelector QuestionTemplate="{StaticResource QuestionTemplate}" InstructionTemplate="{StaticResource InstructionTemplate}" />
        </ItemsControl.ItemTemplateSelector>
    </ItemsControl>
</DockPanel>

Can Some one help me in understanding how this can be archived with smarter design (may be a common base class for Question and have Derived Question class for each Question Type and load the data template using a virtual function from the class...) but I am wondering how this can be done using Template Selector ...or do we need to use some different approach..

1条回答
smile是对你的礼貌
2楼-- · 2019-07-15 14:08

If you create your ViewModel-s derived from a common Quiestion ViewModel, you can create the list (ObservableCollection<Question>). Then use the following ListBox:

<ListBox ItemsSource="{Binding YourQuestionList}">
     <ListBox.Resources>
           <DataTemplate DataType="{x:Type VM:QuestionType1}">
                  ( ... question1 full design ... )
           </DataTemplate>
           <DataTemplate DataType="{x:Type VM:QuestionType2}">
                  ( ... question2 full design ... )
           </DataTemplate>
           ( ... other data templates ... )
</ListBox>

The DataContext will be the specific Question ViewModel inside your custom full design, so you can use those properties for binding, too. You need to add the reference to the namespace your ViewModels are in (eg.: xmlns:VM="clr-namespace:YourApp.VMs") to the top of the xaml file (if your namespace for ViewModels is VMs.

I think this should do the work for you.

查看更多
登录 后发表回答