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!
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>
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) { // ... } }
This solution affects the last row and updates with changes to the underlying collection:
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();
}
}
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>
And a snapshot of it in action
The 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With