WPF - 如何将文本框添加到包含 ItemsControl 的项目的面板

WPF - How to add a textbox to the panel containing the Items of an ItemsControl

我的 ViewModel 具有 MultipleSelectionInfo 类型的属性,如下所示(为清楚起见,我删除了与 PropertyChanged 相关的代码,但我的绑定有效):

public abstract class MultipleSelectionInfo
{
    // A SelectableObject is made of a bool IsSelected and a string ObjectData
    public ObservableCollection<SelectableObject<string>> Items
    { get; set; }

    public string Others
    { get; set; }
}

我这样显示这些属性:

我的 XAML 看起来像这样:

<DataTemplate x:Key="PrepControl">
        <WrapPanel Orientation="Horizontal" HorizontalAlignment="Left">
            <ItemsControl ItemsSource="{Binding Items}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <CheckBox Content="{Binding ObjectData}" IsChecked="{Binding IsSelected}" Margin="0,6,8,0"/>
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

            <TextBox MaxWidth="400" MinWidth="100"
                     MaxHeight="20" Text="{Binding Others}" IsEnabled="{Binding IsOthersSelected}"
                      HorizontalAlignment="Left"/>
        </WrapPanel>
    </DataTemplate>

总而言之,我在 ItemsControl(水平 WrapPanel)中显示 MultipleSelectionInfo 的项目,然后显示 TextBox。最后,我将整个包裹在一个水平的 WrapPanel 中。

问题在于,由于 WrapPanel,TextBox 无法很好地与项目对齐。理想情况下,如果我可以在 ItemsControl 的 WrapPanel 中添加 TextBox,那将修复它。但我做不到。

可能吗?我应该怎么做?我很乐意避免以编程方式操纵 controls/panels 。如果我真的需要,我对 MVVM 不是很熟悉,你愿意解释一下吗?

以下是我期望达到的效果:

通用方法是创建一个 DataTemplateSelector

Typically, you create a DataTemplateSelector when you have more than one DataTemplate for the same type of objects and you want to supply your own logic to choose a DataTemplate to apply based on the properties of each data object

在给定的情况下,我会尝试一个触发器,它修改 Others 项的 ContentTemplate:

<DataTemplate x:Key="PrepControl">
<ItemsControl ItemsSource="{Binding Items}" Grid.Column="1" Name="Lst">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <CheckBox Content="{Binding ObjectData}" 
                            IsChecked="{Binding IsSelected}" 
                            Margin="0,6,8,0">
                    <CheckBox.Style>
                        <Style TargetType="CheckBox">
                            <Style.Triggers>
                                <Trigger Property="Content" Value="Others">
                                    <Setter Property="ContentTemplate">
                                        <Setter.Value>
                                            <DataTemplate>
                                                <StackPanel Orientation="Horizontal">
                                                    <TextBlock Text="{Binding}" VerticalAlignment="Center"/>
                                                    <TextBox Margin="5,0" VerticalAlignment="Center"
                                                                MinWidth="50"
                                                                IsEnabled="{Binding IsChecked, RelativeSource={RelativeSource AncestorType=CheckBox}}"
                                                                Text="{Binding Path=DataContext.Others, ElementName=Lst}"/>
                                                </StackPanel>
                                            </DataTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </CheckBox.Style>
                </CheckBox>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>


通过 Trigger

选择 DataTemplate 的变体
<ItemsControl ItemsSource="{Binding Items}" Grid.Column="1" Name="Lst">
    <ItemsControl.Resources>
        <DataTemplate x:Key="CheckItem">
            <CheckBox Content="{Binding ObjectData}" 
                    IsChecked="{Binding IsSelected}" 
                    Margin="0,6,8,0"/>
        </DataTemplate>

        <DataTemplate x:Key="OthersItem">
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsSelected}" 
                            Content="{Binding ObjectData}"
                            Margin="0,6,8,0"/>
                <TextBox Margin="5,0" VerticalAlignment="Center"
                        MinWidth="50"
                        IsEnabled="{Binding IsSelected}"
                        IsHitTestVisible="True"
                        Text="{Binding Path=DataContext.Others, ElementName=Lst}"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.Resources>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding}">
                <ContentPresenter.Style>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="ContentTemplate" Value="{StaticResource CheckItem}"/>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=ObjectData}" Value="Others">
                                <Setter Property="ContentTemplate" Value="{StaticResource OthersItem}"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentPresenter.Style>
            </ContentPresenter>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>