3 回答
![?](http://img1.sycdn.imooc.com/545865890001495702200220-100-100.jpg)
TA贡献2036条经验 获得超8个赞
我有一个简单的解决方案DataTemplateSelector。它是这样的:
您定义一个选择器,用于区分最后一项。
class LastElementSelector : DataTemplateSelector
{
public DataTemplate NormalTemplate { get; set; }
public DataTemplate LastTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
return IsLast(container) ? LastTemplate : NormalTemplate;
}
bool IsLast(DependencyObject container)
{
var itemsControl = FindParentOrSelf<ItemsControl>(container);
var idx = itemsControl.ItemContainerGenerator.IndexFromContainer(container);
var count = itemsControl.Items.Count;
return idx == count - 1;
}
T FindParentOrSelf<T>(DependencyObject from) where T : DependencyObject
{
for (var curr = from; curr != null; curr = VisualTreeHelper.GetParent(curr))
if (curr is T t)
return t;
return null;
}
}
有了这个,您可以对普通项目和最后项目使用不同的模板:
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplateSelector>
<local:LastElementSelector>
<local:LastElementSelector.NormalTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding Mode=OneWay}"/><!-- no space between runs
--><Run Text="; " Foreground="Red" FontWeight="Bold"/>
</TextBlock>
</DataTemplate>
</local:LastElementSelector.NormalTemplate>
<local:LastElementSelector.LastTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</local:LastElementSelector.LastTemplate>
</local:LastElementSelector>
</ItemsControl.ItemTemplateSelector>
</ItemsControl>
结果:
https://i.stack.imgur.com/RIcQR.gif
![?](http://img1.sycdn.imooc.com/5458506b0001de5502200220-100-100.jpg)
TA贡献1898条经验 获得超8个赞
您的定界符位于下一行的前面,因为它位于 LinkId TextBox 的前面,并且它们都在 WrapPanel 中绑定在一起。整个 WrapPanel 流向下一行。
WrapPanels 上方的父面板不知道也不关心其中的内容。
顺便说一下,我不知道这是否是您的意图,但在您编写的代码中,您为集合中的每个项目生成了一个不同的 WrapPanel。目前,您的测试列表中有 20 个 WrapPanel。
如果像您所说的那样,最后一个分隔符不是问题,那么这是一个足够好的解决方案:
<ItemsControl
ItemsSource="{Binding YourItems}"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
Orientation="Horizontal"
></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel
Orientation="Horizontal"
>
<TextBlock
Text="{Binding LinkId}"
></TextBlock>
<TextBlock
Text="; "
></TextBlock>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
如果这仅用于数据显示目的,请考虑那些行中的文本框很可能是文本框内的单个字符串。也许您可以使用单一格式的字符串并将相关部分制作成链接。这会将操作的字符串分隔符部分移至 ViewModel,并会大大简化您的 XAML 代码。
![?](http://img1.sycdn.imooc.com/545868b60001587202200220-100-100.jpg)
TA贡献1780条经验 获得超5个赞
您可以尝试将定界符放在文本之后,并通过将其属性设置为空字符串来隐藏最后一个Run元素:Text
<ItemsControl AlternationCount="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding Path=., Mode=OneWay}" /><Run x:Name="delimiter" Text="; "/>
</TextBlock>
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Text" TargetName="delimiter" Value=""/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
这应该使分隔符和文本保持在同一行。
- 3 回答
- 0 关注
- 92 浏览
添加回答
举报