How can a separator be added between items in an ItemsControl
<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>
I arrived at your question because I was looking for a solution in Silverlight, which does not have a previous data relative source.
(WPF) How can a separator be added between items in an ItemsControl - Bug Fixing
It was not easy,but I realized what shall I do to fix this bug. My idea is to use custom Convertor, but I haven't any clever thoughts How to send ConverterParameter into convertor. But I've found solution.
Here is my convertor:
public class SeparatorConverter : IValueConverter
{
private Visibility _visible;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var element = (TextBlock) value;
element.Loaded += ElementLoaded;
return _visible;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null; //not needed
}
private static void ElementLoaded(object sender, RoutedEventArgs e)
{
var element = sender as TextBlock;
var parentItemsControl = element.FindParent(x => x is ItemsControl) as ItemsControl;
var parentPanel = element.FindParent(x => x is Panel) as Panel;
if (parentItemsControl == null || element == null || parentPanel== null)
return;
var itemText = parentPanel.FindName("MyTextBlock") as TextBlock;
var collection = parentItemsControl.ItemsSource as IEnumerable<string>;
if (itemText == null || collection == null)
return;
var list = collection.ToList();
if (list.IndexOf(itemText.Text) == list.Count() - 1) // Can be incorrect because we can have two same items
element.Visibility = Visibility.Collapsed;
}
}
Find parent function:
public static DependencyObject FindParent(this DependencyObject element, Func<DependencyObject, bool> filter)
{
DependencyObject parent = VisualTreeHelper.GetParent(element);
if (parent != null)
{
if (filter(parent))
{
return parent;
}
return FindParent(parent, filter);
}
return null;
}
Here is my XAML code:
<Coverters:SeparatorConverter x:Key="SeparatorVisibilityConverter">
</Coverters:SeparatorConverter>
<ItemsControl Grid.Row="1" ItemsSource="{Binding Value, IsAsync=False}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel>
</WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock x:Name="MyTextBlock" Text="{Binding}" Style="{StaticResource TextBlockInListViewItem}" TextWrapping="WrapWithOverflow"/>
<TextBlock x:Name="commaTextBlock" Style="{StaticResource TextBlockInListViewItem}" Text=", " Visibility="{Binding RelativeSource={RelativeSource Self},
Converter={StaticResource SeparatorVisibilityConverter}}"/>
</WrapPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Ok. Any way, If you have another idea how to fix this bug, you could post your answer here=)
WPF how to put separator below each item in horizontal stackpanel
make the first stackpanel vertical and put the content control and the label inside of a horizontal stackpanel. something like this:
<StackPanel>
<StackPanel Orientation="Horizontal">
<ContentControl Content="{StaticResource Appbar_Suitcase}" />
<Label Content="{Binding Name}"/>
</StackPanel>
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
</StackPanel>
ListView separator between items
You need to use a DataTemplateSelector
for this. First you need to create Two DataTemplate
's
For example: In a simple ItemsControl which I want to show you a list of String, My Two DataTemplate
's would look like below.
<Page.Resources>
<DataTemplate x:Name="AllItems">
<Border BorderBrush="{StaticResource SystemControlBackgroundBaseLowBrush}" BorderThickness="0,0,0,2">
<TextBlock Text="{Binding ''}" Padding="10" Margin="10,0" />
</Border>
</DataTemplate>
<DataTemplate x:Name="LastItems">
<TextBlock Text="{Binding ''}" Padding="10" Margin="10,0" />
</DataTemplate>
</Page.Resources>
Now I create a DataTemplateSelector
and Check if the Item that I need to apply the DataTemplate
is Last one or not.
public class ItemsDataTemplateSelector: DataTemplateSelector
{
public DataTemplate AllItems { get; set; }
public DataTemplate LastItems { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
DataTemplate _returnTemplate = new DataTemplate();
var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
if (itemsControl.IndexFromContainer(container) == (itemsControl.ItemsSource as List<String>).Count-1)
{
_returnTemplate = LastItems;
}
else
{
_returnTemplate = AllItems;
}
return _returnTemplate;
}
}
Now my ItemsControl
Implementation would be
<ItemsControl x:Name="listView">
<ItemsControl.ItemTemplateSelector>
<local:ItemsDataTemplateSelector AllItems="{StaticResource AllItems}" LastItems="{StaticResource LastItems}" />
</ItemsControl.ItemTemplateSelector>
</ItemsControl>
Here is how i set the ItemsSource to ItemsControl
List<String> items = new List<string>();
for (int i = 1; i <= 5; i++)
{
items.Add("Item " + i.ToString());
}
listView.ItemsSource = items;
Below is your output. You can see Last Item does not have a Border
Separator in ItemsControl renders in different shades for each item
Try SnapsToDevicePixels="True"
<ItemsControl ItemsSource="{Binding Path=Items}" SnapsToDevicePixels="True">
If this doesn't help you can also try with
UseLayoutRounding="True"
(WPF 4)RenderOptions.EdgeMode="Aliased"
(Turn of anti-aliasing)
Text separator between ListView in WPF
Duplicate of How can a separator be added between items in an ItemsControl, try this:
<ItemsControl Name="theListBox">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="seperator" Text=" | "/>
<TextBlock Text="{Binding}"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter Property="Visibility" TargetName="seperator" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Stretching the items of an ItemsControl
You have two columns in your main (outer) grid, yet you use only the first column.
The second column uses all the remaining space.
Related Topics
How to Detect If Type Is Another Generic Type
How to Get the Actual Monitor Name? as Seen in the Resolution Dialog
How to Call a Variable in Code Behind to Aspx Page
Get Ssid of the Wireless Network I am Connected to with C# .Net on Windows Vista
How to Call C# Dll Function from Vbscript
How to Use Dependency Injection with an Attribute
Should You Implement Idisposable.Dispose() So That It Never Throws
Why Use Async/Await All the Way Down
JSON String to CSV and CSV to JSON Conversion in C#
How to Convert Bitarray to Single Int
How to Get Files in a Relative Path in C#
Force Browser to Download PDF Document Instead of Opening It
Entity Framework and Business Objects
Generic Base Class for Winform Usercontrol
How to Find System.Web.Helpers, System.Web.Webpages, and System.Web.Razor