2010-03-24 131 views
53

我需要在項目控件中顯示集合中的數字列表。所以這些項目是:「1」,「2」,「3」。如何在項目控件中的項目之間添加分隔符

當它們呈現時,我需要用逗號(或類似的東西)分隔它們。所以上面的3個項目看起來像這樣:「1,2,3」。

如何在單個項目中添加分隔符而不在列表的末尾添加分隔符?

我並沒有停留在使用ItemsControl,但這就是我已經開始使用。

回答

98
<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中尋找一個解決方案,它沒有以前的數據相關源。

+1

@foson:我從來沒有找到過。我最終使用了一個負邊距來「截斷」文本中的尾部「,」。它感覺很髒,但它工作。 – 2011-11-12 10:06:18

+0

Silverlight中的'PreviousData'的任何解決方法? – Shimmy 2012-03-27 23:52:27

+0

如何使用項目的索引並將其與零比較? – MikeKulls 2012-05-07 05:49:31

1

我想我應該給我解決的辦法。

我最終將我的項目集合綁定到TextBlock的Text,並使用值轉換器將項目的綁定集合更改爲格式化的字符串。

3

您也可以將多重綁定到ItemsControl.AlternationIndex和ItemsControl.Count並將AlternationIndex與Count進行比較以查看您是否是最後一項。

設置AlternationIndex高到足以容納你所有的物品然後進行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; 
    } 
+0

可以在模板中的項目內容之前放置分隔線。然後,僅綁定到** AlternationIndex **並將分隔符隱藏在第一項(AlternationIndex == 0)中就足夠了。 – baSSiLL 2016-09-01 11:54:46

4

對於一個更廣義的Silverlight的兼容的解決方案,我得到的控制自ItemsControl( SeperatedItemsControl)。每個項目都包裝在一個SeperatedItemsControlItem中,就像ListBox的ListBoxItem一樣。 SeperatedItemsControlItem的模板包含一個分隔符和一個ContentPresenter。集合中第一個元素的分隔符是隱藏的。您可以輕鬆修改此解決方案,以在物品之間製作水平條紋分隔線,這是我爲其創建的。

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; 
       } 
      } 
     } 
    } 
} 
14

The current accepted answer給了我一個XAML每一個模板,我擔心可能會影響性能綁定錯誤。相反,我做了以下操作,使用AlternationIndex隱藏第一個分隔符。 (靈感來自this answer。)

<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> 
+1

好笑。在使用接受的答案改變了列表計數之後,我的逗號出現問題後,我回到了這裏。您的解決方案解決了我的問題,謝謝! – 2016-01-14 17:09:00

+1

太好了 - 謝謝@Carter! – Chris 2016-01-15 11:28:56

+0

對於我而言,此線上沒有圓點 而不是 luka 2017-10-08 18:13:23

相關問題