Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use different template for last item in a WPF itemscontrol

I'm using a custom template in my itemscontrol to display the following result:

item 1, item 2, item3,

I want to change the template of the last item so the result becomes:

item 1, item2, item3

The 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>

Is there anyone who can give a solution for my problem? Thank you!

like image 423
Bram W. Avatar asked Oct 14 '11 11:10

Bram W.


3 Answers

I've found the solution for my problem using only XAML. If there is anybody who needs to do the same, use this:

<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> 
like image 76
Bram W. Avatar answered Sep 17 '22 13:09

Bram W.


You can use DataTemplateSelector, in SelectTemplate() method you can check whether item is the last and then return an other template.

In XAML:

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

In Code behind:

 private sealed class MyTemplateSelector: DataTemplateSelector  {       public override DataTemplate SelectTemplate(                                       object item,                                        DependencyObject container)     {         // ...     }   } 
like image 38
sll Avatar answered Sep 21 '22 13:09

sll


This solution affects the last row and updates with changes to the underlying collection:


CodeBehind

The converter requires 3 parameters to function properly - the current item, the itemscontrol, the itemscount, and returns true if current item is also last item:

  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

The Data-Trigger for a DataTemplate, that includes a textbox named 'PART_TextBox':

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

The converter as a static resource in the Xaml

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

SnapShot

And a snapshot of it in action

enter image description hereThe code has been added to the itemscontrol from this 'codeproject' https://www.codeproject.com/Articles/242628/A-Simple-Cross-Button-for-WPF

Note the last item's text in red

like image 33
Declan Taylor Avatar answered Sep 17 '22 13:09

Declan Taylor