代码之家  ›  专栏  ›  技术社区  ›  Nathan

如何在ItemsControl中的项之间添加分隔符

  •  55
  • Nathan  · 技术社区  · 14 年前

    我需要在Items控件中显示集合中的数字列表。因此,这些项目是: "1", "2", "3" .

    "1, 2, 3" .

    5 回复  |  直到 6 年前
        1
  •  114
  •   Matt Becker    10 年前
    <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中寻找一个解决方案,它没有以前的数据相对源。

        2
  •  28
  •   Community c0D3l0g1c    7 年前

    The current accepted answer 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>
    
        3
  •  5
  •   foson    13 年前

    对于更通用的Silverlight兼容解决方案,我从ItemsControl(separateditemscontrol)派生了一个控件。每个项都被包装在一个单独的ditemscontrolitem中,就像ListBox的ListBoxItem一样。SeparatedItemControlItem的模板包含分隔符和ContentPresenter。集合中第一个元素的分隔符被隐藏。您可以很容易地修改这个解决方案,使项目之间的水平条分隔符,这就是我创建它的目的。

    主窗口.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>
    

    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;
                    }
                }
            }
        }
    }
    
        4
  •  4
  •   Mo0gles    14 年前

    您还可以多绑定到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;
        }
    
        5
  •  1
  •   Nathan    14 年前

    我想我应该给出最终的解决方案。

    最后,我将项目集合绑定到TextBlock的文本,并使用值转换器将绑定的项目集合更改为格式化的字符串。