在 ItemsControl 中添加不同的控件

Add different controls in ItemsControl

我需要根据特定条件在 ItemsControl 中添加不同的控件(TextBox/CheckBox/ComboBox,等等)。 ItemsControl 中的每个 Item 都是一个名称-值对。名称始终由 TextBlock 表示,但值可以是任何 UI 控件。 我使用水平对齐的 StackPanel 来表示每个项目。 StackPanel 中的第一个控件仍然是 TextBlock,但第二个控件依赖于运行时在 ViewModel 中设置的 "ItemDataType" 属性。

我遇到的问题是我无法使用带 ItemDataType 的 Style 触发器在 StackPanel 的第二个元素中分配不同的控件 属性。

代码片段:

<UserControl.Resources>

    <DataTemplate x:Key="TextBoxTemplate">
        <TextBox Text="{Binding Path=DataValue}"/>
    </DataTemplate>

    <DataTemplate x:Key="ComboBoxTemplate">
        <ComboBox ItemsSource="{Binding Path=SelectionList}" SelectedValue="{Binding Path=DataValue,Mode=TwoWay}"/>
    </DataTemplate>

    <DataTemplate x:Key="CheckBoxTemplate">
        <CheckBox IsChecked="{Binding Path=DataValue,Mode=TwoWay}" />
    </DataTemplate>

    <DataTemplate x:Key="ButtonTemplate">
        <Button Content="{Binding Path=DataValue}"/>
    </DataTemplate>

    <DataTemplate x:Key="dynamicTemplate">
        <StackPanel Orientation="Horizontal" Tag="{Binding ItemDataType}">
            <TextBlock Text="{Binding Path=DataName,Mode=TwoWay}"/>
            <ContentControl>
                <ContentControl.Style>
                    <Style TargetType="{x:Type ContentControl}">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding ItemDataType}" Value="TextBox">
                                <Setter Property="Template" Value="{StaticResource TextBoxTemplate}"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>
        </StackPanel>
    </DataTemplate>

</UserControl.Resources>

<Grid>
    <!-- CONTROL LAYOUT -->
    <ItemsControl ItemsSource="{Binding Path=DataList,Mode=TwoWay}" ItemTemplate="{StaticResource dynamicTemplate}">

        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</Grid>

我得到的错误是 DataTemplate 对 ContentControl.Template 属性 无效。我明白我的做法是错误的,但我需要帮助以正确的方式做事。

谢谢,

RDV

我想要一个 XAML 解决方案 - 花了我一些时间:-)。 以下是工作代码:

    <Style x:Key="nvpTextBlockStyle" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type TextBlock}}">
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="Width" Value="{Binding Path=LabelWidthStr, FallbackValue=50}"/>
        <Setter Property="Margin" Value="0,5,0,5"/>
        <Setter Property="Text" Value="{Binding Path=NameData,Mode=TwoWay}"/>
        <Setter Property="FontSize" Value="16"/>
    </Style>

    <DataTemplate x:Key="textBoxTemplate">
        <TextBox Margin="1,1" Text="{Binding Path=ValueData,UpdateSourceTrigger=PropertyChanged,
                    ValidatesOnExceptions=True,NotifyOnValidationError=True,ValidatesOnDataErrors=True}"/>
    </DataTemplate>

    <DataTemplate x:Key="comboBoxTemplate">
        <ComboBox HorizontalAlignment="Left" ItemsSource="{Binding Path=SelectionList}" 
                      SelectedValue="{Binding Path=ValueData,Mode=TwoWay}"
                      IsEnabled="{Binding IsDataItemEnabled}"/>
    </DataTemplate>

    <DataTemplate x:Key="checkBoxTemplate">
        <CheckBox HorizontalAlignment="Left" VerticalAlignment="Center"  
                      IsChecked="{Binding Path=ValueData,Mode=TwoWay}"/>
    </DataTemplate>

    <DataTemplate x:Key="buttonTemplate">
        <Button Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.AddCommand}" 
                    CommandParameter="{Binding}" Width="30" Height="25">
            <TextBlock Text="&#x1F511;" FontFamily="Segoe UI Symbol" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Gray" />
        </Button>
    </DataTemplate>

    <DataTemplate x:Key="dynamicTemplate">
        <StackPanel Orientation="Horizontal" Margin ="5">
            <TextBlock Style="{StaticResource nvpTextBlockStyle}"/>
            <ContentPresenter Content="{Binding}" 
                Tag="{Binding Path=CustomDataType, FallbackValue={x:Static local:CustomViewModel.TEXTBOX_TEMPLATE}}">
                <ContentPresenter.Resources>
                    <Style TargetType="{x:Type ContentPresenter}">
                        <Style.Triggers>
                            <Trigger Property="Tag" Value="{x:Static local:CustomViewModel.TEXTBOX_TEMPLATE}">
                                <Setter Property="ContentTemplate" Value="{StaticResource textBoxTemplate}"/>
                            </Trigger>
                            <Trigger Property="Tag" Value="{x:Static local:CustomViewModel.COMBOBOX_TEMPLATE}">
                                <Setter Property="ContentTemplate" Value="{StaticResource comboBoxTemplate}"/>
                            </Trigger>
                            <Trigger Property="Tag" Value="{x:Static local:CustomViewModel.CHECKBOX_TEMPLATE}">
                                <Setter Property="ContentTemplate" Value="{StaticResource checkBoxTemplate}"/>
                            </Trigger>
                            <Trigger Property="Tag" Value="{x:Static local:CustomViewModel.BUTTON_TEMPLATE}">
                                <Setter Property="ContentTemplate" Value="{StaticResource buttonTemplate}"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </ContentPresenter.Resources>
            </ContentPresenter>
        </StackPanel>
    </DataTemplate>

    <Grid>       
    <ScrollViewer VerticalScrollBarVisibility="Auto">
        <ItemsControl  ItemsSource="{Binding Path=CustomDataList,Mode=TwoWay}" 
                       ItemTemplate="{StaticResource dynamicTemplate}";
                       KeyboardNavigation.IsTabStop="False">
            <ItemsPanelTemplate>
                <StackPanel></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl>
    </ScrollViewer>

</Grid>

谢谢,

RDV