如何在ItemsControl中的项目之间添加分隔符
我需要在Items Control中显示一个集合中的数字列表。 所以项目是:“1”,“2”,“3”。
当它们被渲染时,我需要用逗号(或类似的东西)来分隔它们。 所以上面的3个项目看起来是这样的:“1,2,3”。
我怎样才能添加一个分隔符到单个项目,而没有一个钉在列表的最后?
我没有停留在使用ItemsControl,但这就是我已经开始使用。
<ItemsControl ItemsSource="{Binding Numbers}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <!-- could use a WrapPanel if more appropriate for your scenario --> <StackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock x:Name="commaTextBlock" Text=", "/> <TextBlock Text="{Binding .}"/> </StackPanel> <DataTemplate.Triggers> <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}"> <Setter Property="Visibility" TargetName="commaTextBlock" Value="Collapsed"/> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
我到了你的问题,因为我正在寻找Silverlight的解决scheme,没有以前的数据相关源。
目前接受的答案给了我每个模板的xaml绑定错误,我担心可能会影响性能。 相反,我做了以下,使用AlternationIndex来隐藏第一个分隔符。 (受这个答案的启发。)
<ItemsControl ItemsSource="{Binding Numbers}" AlternationCount="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock x:Name="SeparatorTextBlock" Text=", "/> <TextBlock Text="{Binding .}"/> </StackPanel> <DataTemplate.Triggers> <Trigger Property="ItemsControl.AlternationIndex" Value="0"> <Setter Property="Visibility" TargetName="SeparatorTextBlock" Value="Collapsed" /> </Trigger> </DataTemplate.Triggers> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
对于更通用的Silverlight兼容解决scheme,我从ItemsControl(SeperatedItemsControl)派生了一个控件。 每个项目都被包装在一个SeperatedItemsControlItem中,就像ListBox的ListBoxItem一样。 SeperatedItemsControlItem的模板包含一个分隔符和一个ContentPresenter。 集合中第一个元素的分隔符是隐藏的。 你可以很容易的修改这个解决scheme,在物品之间做一个横向的分隔线,这是我为它创build的。
MainWindow.xaml:
<Window x:Class="ItemsControlWithSeperator.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ItemsControlWithSeperator" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <UserControl.Resources> <local:ViewModel x:Key="vm" /> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource vm}"> <local:SeperatedItemsControl ItemsSource="{Binding Data}"> <local:SeperatedItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </local:SeperatedItemsControl.ItemsPanel> <local:SeperatedItemsControl.ItemContainerStyle> <Style TargetType="local:SeperatedItemsControlItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:SeperatedItemsControlItem" > <StackPanel Orientation="Horizontal"> <TextBlock x:Name="seperator">,</TextBlock> <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}"/> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </local:SeperatedItemsControl.ItemContainerStyle> </local:SeperatedItemsControl> </Grid>
C#代码:
using System; using System.Windows; using System.Windows.Controls; namespace ItemsControlWithSeperator { public class ViewModel { public string[] Data { get { return new[] { "Amy", "Bob", "Charlie" }; } } } public class SeperatedItemsControl : ItemsControl { public Style ItemContainerStyle { get { return (Style)base.GetValue(SeperatedItemsControl.ItemContainerStyleProperty); } set { base.SetValue(SeperatedItemsControl.ItemContainerStyleProperty, value); } } public static readonly DependencyProperty ItemContainerStyleProperty = DependencyProperty.Register("ItemContainerStyle", typeof(Style), typeof(SeperatedItemsControl), null); protected override DependencyObject GetContainerForItemOverride() { return new SeperatedItemsControlItem(); } protected override bool IsItemItsOwnContainerOverride(object item) { return item is SeperatedItemsControlItem; } protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { //begin code copied from ListBox class if (object.ReferenceEquals(element, item)) { return; } ContentPresenter contentPresenter = element as ContentPresenter; ContentControl contentControl = null; if (contentPresenter == null) { contentControl = (element as ContentControl); if (contentControl == null) { return; } } DataTemplate contentTemplate = null; if (this.ItemTemplate != null && this.DisplayMemberPath != null) { throw new InvalidOperationException(); } if (!(item is UIElement)) { if (this.ItemTemplate != null) { contentTemplate = this.ItemTemplate; } } if (contentPresenter != null) { contentPresenter.Content = item; contentPresenter.ContentTemplate = contentTemplate; } else { contentControl.Content = item; contentControl.ContentTemplate = contentTemplate; } if (ItemContainerStyle != null && contentControl.Style == null) { contentControl.Style = ItemContainerStyle; } //end code copied from ListBox class if (this.Items.Count > 0) { if (object.ReferenceEquals(this.Items[0], item)) { var container = element as SeperatedItemsControlItem; container.IsFirstItem = true; } } } protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { base.OnItemsChanged(e); if (Items.Count > 1) { var container = (ItemContainerGenerator.ContainerFromIndex(1) as SeperatedItemsControlItem); if (container != null) container.IsFirstItem = false; } if (Items.Count > 0) { var container = (ItemContainerGenerator.ContainerFromIndex(0) as SeperatedItemsControlItem); if (container != null) container.IsFirstItem = true; } } } public class SeperatedItemsControlItem : ContentControl { private bool isFirstItem; public bool IsFirstItem { get { return isFirstItem; } set { if (isFirstItem != value) { isFirstItem = value; var seperator = this.GetTemplateChild("seperator") as FrameworkElement; if (seperator != null) { seperator.Visibility = isFirstItem ? Visibility.Collapsed : Visibility.Visible; } } } } public override void OnApplyTemplate() { base.OnApplyTemplate(); if (IsFirstItem) { var seperator = this.GetTemplateChild("seperator") as FrameworkElement; if (seperator != null) { seperator.Visibility = Visibility.Collapsed; } } } } }
您也可以多项绑定到ItemsControl.AlternationIndex和ItemsControl.Count并比较AlternationIndex计数,看看你是否是最后一个项目。
将AlternationIndex设置得足够高,以容纳所有的项目,然后用Convert方法创build一个LastItemConverter,如下所示:
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var alterationCount = (int)values[0]; var itemCount = (int)values[1]; if (itemCount > 1) { return alterationCount == (itemCount - 1) ? Visibility.Collapsed : Visibility.Visible; } return Visibility.Collapsed; }
我想我应该给我解决的办法。
我最终将我的项目集合绑定到TextBlock的Text,并使用值转换器将项目的绑定集合更改为格式化的string。