ItemsControl 包装问题

我做了一些小的自定义 ItemsControl 来将一些列表显示为项目行。它几乎完美地工作。


<ItemsControl.ItemTemplate>

    <DataTemplate>

       <WrapPanel Orientation="Horizontal">

           <TextBlock x:Name="delimiter" Text=";" Margin="0 0 5 0"/>

           <TextBlock Text="{Binding LinkId}" />

       </WrapPanel>

       <DataTemplate.Triggers>

          <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">

              <Setter Property="Visibility" TargetName="delimiter" Value="Collapsed"/>

          </DataTrigger>

        </DataTemplate.Triggers>

    </DataTemplate>

</ItemsControl.ItemTemplate>

我的问题在定界符中:当 ItemsConteol 换行到下一行时,定界符 char 会从下一行开始。


我知道问题出在哪里,但我不知道如何解决。

http://img1.mukewang.com/637b3ce80001f0f706460073.jpg

慕码人2483693
浏览 93回答 3
3回答

慕桂英3389331

我有一个简单的解决方案DataTemplateSelector。它是这样的:您定义一个选择器,用于区分最后一项。class LastElementSelector : DataTemplateSelector{&nbsp; &nbsp; public DataTemplate NormalTemplate { get; set; }&nbsp; &nbsp; public DataTemplate LastTemplate { get; set; }&nbsp; &nbsp; public override DataTemplate SelectTemplate(object item, DependencyObject container)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return IsLast(container) ? LastTemplate : NormalTemplate;&nbsp; &nbsp; }&nbsp; &nbsp; bool IsLast(DependencyObject container)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var itemsControl = FindParentOrSelf<ItemsControl>(container);&nbsp; &nbsp; &nbsp; &nbsp; var idx = itemsControl.ItemContainerGenerator.IndexFromContainer(container);&nbsp; &nbsp; &nbsp; &nbsp; var count = itemsControl.Items.Count;&nbsp; &nbsp; &nbsp; &nbsp; return idx == count - 1;&nbsp; &nbsp; }&nbsp; &nbsp; T FindParentOrSelf<T>(DependencyObject from) where T : DependencyObject&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; for (var curr = from; curr != null; curr = VisualTreeHelper.GetParent(curr))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (curr is T t)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return t;&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }}有了这个,您可以对普通项目和最后项目使用不同的模板:<ItemsControl ItemsSource="{Binding}">&nbsp; &nbsp; <ItemsControl.ItemsPanel>&nbsp; &nbsp; &nbsp; &nbsp; <ItemsPanelTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <WrapPanel IsItemsHost="True"/>&nbsp; &nbsp; &nbsp; &nbsp; </ItemsPanelTemplate>&nbsp; &nbsp; </ItemsControl.ItemsPanel>&nbsp; &nbsp; <ItemsControl.ItemTemplateSelector>&nbsp; &nbsp; &nbsp; &nbsp; <local:LastElementSelector>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <local:LastElementSelector.NormalTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <DataTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TextBlock>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Run Text="{Binding Mode=OneWay}"/><!-- no space between runs&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --><Run Text="; " Foreground="Red" FontWeight="Bold"/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </TextBlock>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </DataTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </local:LastElementSelector.NormalTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <local:LastElementSelector.LastTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <DataTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TextBlock Text="{Binding}"/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </DataTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </local:LastElementSelector.LastTemplate>&nbsp; &nbsp; &nbsp; &nbsp; </local:LastElementSelector>&nbsp; &nbsp; </ItemsControl.ItemTemplateSelector></ItemsControl>结果:https://i.stack.imgur.com/RIcQR.gif

汪汪一只猫

您的定界符位于下一行的前面,因为它位于 LinkId TextBox 的前面,并且它们都在 WrapPanel 中绑定在一起。整个 WrapPanel 流向下一行。WrapPanels 上方的父面板不知道也不关心其中的内容。顺便说一下,我不知道这是否是您的意图,但在您编写的代码中,您为集合中的每个项目生成了一个不同的 WrapPanel。目前,您的测试列表中有 20 个 WrapPanel。如果像您所说的那样,最后一个分隔符不是问题,那么这是一个足够好的解决方案:&nbsp; &nbsp; <ItemsControl&nbsp; &nbsp; &nbsp; &nbsp; ItemsSource="{Binding YourItems}"&nbsp; &nbsp; &nbsp; &nbsp; >&nbsp; &nbsp; &nbsp; &nbsp; <ItemsControl.ItemsPanel>&nbsp; &nbsp; &nbsp; &nbsp; <ItemsPanelTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <WrapPanel&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Orientation="Horizontal"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ></WrapPanel>&nbsp; &nbsp; &nbsp; &nbsp; </ItemsPanelTemplate>&nbsp; &nbsp; &nbsp; &nbsp; </ItemsControl.ItemsPanel>&nbsp; &nbsp; &nbsp; &nbsp; <ItemsControl.ItemTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <DataTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <StackPanel&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Orientation="Horizontal"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TextBlock&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text="{Binding LinkId}"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ></TextBlock>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TextBlock&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text="; "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ></TextBlock>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </StackPanel>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </DataTemplate>&nbsp; &nbsp; &nbsp; &nbsp; </ItemsControl.ItemTemplate>&nbsp; &nbsp; </ItemsControl>如果这仅用于数据显示目的,请考虑那些行中的文本框很可能是文本框内的单个字符串。也许您可以使用单一格式的字符串并将相关部分制作成链接。这会将操作的字符串分隔符部分移至 ViewModel,并会大大简化您的 XAML 代码。

翻阅古今

您可以尝试将定界符放在文本之后,并通过将其属性设置为空字符串来隐藏最后一个Run元素:Text<ItemsControl AlternationCount="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}">&nbsp; &nbsp; <ItemsControl.ItemsPanel>&nbsp; &nbsp; &nbsp; &nbsp; <ItemsPanelTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <WrapPanel Orientation="Horizontal" />&nbsp; &nbsp; &nbsp; &nbsp; </ItemsPanelTemplate>&nbsp; &nbsp; </ItemsControl.ItemsPanel>&nbsp; &nbsp; <ItemsControl.ItemTemplate>&nbsp; &nbsp; &nbsp; &nbsp; <DataTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TextBlock>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Run Text="{Binding Path=., Mode=OneWay}" /><Run x:Name="delimiter" Text=";&nbsp; &nbsp; "/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </TextBlock>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <DataTemplate.Triggers>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Trigger Property="ItemsControl.AlternationIndex" Value="0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Setter Property="Text" TargetName="delimiter" Value=""/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </Trigger>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </DataTemplate.Triggers>&nbsp; &nbsp; &nbsp; &nbsp; </DataTemplate>&nbsp; &nbsp; </ItemsControl.ItemTemplate></ItemsControl>这应该使分隔符和文本保持在同一行。
打开App,查看更多内容
随时随地看视频慕课网APP