对WPF项目控件中的最后一项使用不同的模板

时间:2011-10-14 11:41:31

标签: wpf templates itemscontrol

我在itemscontrol中使用自定义模板来显示以下结果:

item 1, item 2, item3,

我想更改最后一项的模板,结果如下:

item 1, item2, item3

ItemsControl:

<ItemsControl ItemsSource="{Binding Path=MyCollection}">

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" IsItemsHost="True"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>

            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Path=Name}"/>
                <TextBlock Text=", "/>
            </StackPanel>

        </DataTemplate>
    </ItemsControl.ItemTemplate>

</ItemsControl>

有没有人可以为我的问题提供解决方案?谢谢!

4 个答案:

答案 0 :(得分:53)

我只使用XAML找到了问题的解决方案。如果有人需要这样做,请使用:

<ItemsControl ItemsSource="{Binding Path=MyCollection}">

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" IsItemsHost="True"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>

            <StackPanel Orientation="Horizontal">
                <TextBlock x:Name="comma" Text=", "/>
                <TextBlock Text="{Binding}"/>
            </StackPanel>

            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
                    <Setter TargetName="comma" Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
            </DataTemplate.Triggers>

        </DataTemplate>
    </ItemsControl.ItemTemplate>

</ItemsControl>

答案 1 :(得分:7)

您可以使用DataTemplateSelector,在SelectTemplate()方法中,您可以检查项目是否为最后一项,然后返回其他模板。

在XAML中:

<ItemsControl.ItemTemplate>     
  <DataTemplate>
      <ContentPresenter 
             ContentTemplateSelector = "{StaticResource MyTemplateSelector}">

在代码背后:

 private sealed class MyTemplateSelector: DataTemplateSelector
 { 

    public override DataTemplate SelectTemplate(
                                      object item, 
                                      DependencyObject container)
    {
        // ...
    }
  }

答案 2 :(得分:2)

此解决方案影响最后一行并更新基础集合:

代码隐藏

转换器需要3个参数才能正常运行 - 当前项目,itemscontrol,itemscount,如果当前项目也是最后一项,则返回true:

  class LastItemConverter : IMultiValueConverter
    {

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            int count = (int)values[2];

            if (values != null && values.Length == 3 && count>0)
            {
                System.Windows.Controls.ItemsControl itemsControl = values[0] as System.Windows.Controls.ItemsControl;
                var itemContext = (values[1] as System.Windows.Controls.ContentPresenter).DataContext;

                var lastItem = itemsControl.Items[count-1];

                return Equals(lastItem, itemContext);
            }

            return DependencyProperty.UnsetValue;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

XAML

DataTemplate的数据触发器,其中包含名为&#39; PART_TextBox&#39;的文本框:

  <DataTemplate.Triggers>
            <DataTrigger Value="True" >
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource LastItemConverter}">
                        <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}" />
                        <Binding RelativeSource="{RelativeSource Self}"/>
                        <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}" Path="Items.Count"/>
                    </MultiBinding>
                </DataTrigger.Binding>
                <Setter Property="Foreground" TargetName="PART_TextBox" Value="Red" />
            </DataTrigger>
 </DataTemplate.Triggers>      

转换器作为Xaml中的静态资源

<Window.Resources>
     <local:LastItemConverter x:Key="LastItemConverter" />
</Window.Resources>

快照

它的实际快照

enter image description here代码已添加到此&#39;代码项目&#39;中的itemscontrol中。 https://www.codeproject.com/Articles/242628/A-Simple-Cross-Button-for-WPF

请注意最后一项红色

的文字

答案 3 :(得分:0)

一个问题......我看到你使用的是ItemsControl,而不是说ListBox,而且它似乎绑定了一系列字符串,而你只是在尝试显示结果文本而不格式化各个部分,这让我想知道你想要的输出实际上是问题中提到的字符串本身,而不是实际的ItemsControl本身。

如果我对此是正确的,你是否考虑过只使用一个简单的TextBlock绑定到items集合,但通过转换器?然后在转换器内部,你将value转换为一个字符串数组,然后在Convert方法中,只需Join使用逗号作为分隔符,它们将自动添加它们元素,像这样......

var strings = (IEnumerable<String>)value;

return String.Join(", ", strings);