Is there any way to get the index of the current ItemsControl
item in WPF
?
For example, I want to do something like:
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding current_index}">
</TextBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
so that after this, the first TextBox
will show text "0"
, second "1"
, third "2" ...
.
I would suggest looking at:
WPF ItemsControl the current ListItem Index in the ItemsSource
It explains how to work around the fact that there isn't a built in Index property on the ItemsControl.
EDIT:
I tried the following code:
<Window.Resources>
<x:Array Type="{x:Type sys:String}" x:Key="MyArray">
<sys:String>One</sys:String>
<sys:String>Two</sys:String>
<sys:String>Three</sys:String>
</x:Array>
</Window.Resources>
<ItemsControl ItemsSource="{StaticResource MyArray}" AlternationCount="100" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource TemplatedParent},
StringFormat={}Index is {0}}">
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl >
And get a window with three TextBlocks like:
[Index is 0]
[Index is 1]
[Index is 2]
Check this out
<ItemsControl ItemsSource="{Binding Items}" Name="lista">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource converter}">
<Binding Path="."/>
<Binding ElementName="lista" Path="ItemsSource"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Converter looks like this
public class conv : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ObservableCollection<string> lista = (ObservableCollection<string>)values[1];
return String.Concat(lista.IndexOf(values[0].ToString()), " ", values[0].ToString());
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
As a result

Here how I get ItemIndex
<ItemsControl>
<ItemsControl.Resources>
<CollectionViewSource x:Key="ProductItems" Source="{Binding SelectedScanViewModel.Products}">
<CollectionViewSource.SortDescriptions>
<componentModel:SortDescription PropertyName="ProductName" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</ItemsControl.Resources>
<ItemsControl.ItemsSource>
<Binding Source="{StaticResource ProductItems}"/>
</ItemsControl.ItemsSource>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Center">
<TextBlock Text="{Binding ProductName}" HorizontalAlignment="Center" />
<TextBox Name="txtFocus" Text="{Binding Qty}" MinWidth="80" HorizontalAlignment="Center"
behaviors:SelectTextOnFocus.Active="True">
<TextBox.TabIndex>
<MultiBinding Converter="{StaticResource GetIndexMultiConverter}" ConverterParameter="0">
<Binding Path="."/>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}" Path="ItemsSource"/>
</MultiBinding>
</TextBox.TabIndex>
</TextBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding SelectedScanViewModel.Products.Count}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
And the converter:
public class GetIndexMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var collection = (ListCollectionView)values[1];
var itemIndex = collection.IndexOf(values[0]);
return itemIndex;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException("GetIndexMultiConverter_ConvertBack");
}
}
By this way you can bind every type of collection to the ItemSource and he will be change to ListCollectionView. So the converter will work for different collection type.
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
I did it via the converter that calculate the index of added element.
It works one way only. If you delete items somehow or collection changing you shoud to use thomething else. And you shoud to create separate converter for every collection which elements you need to be indexed.
public class LineMultiplierConverter : IValueConverter
{
private int m_lineIndex = 0;
Line m_curentLine = null;
/// <summary>
/// Base value that will be multiplied
/// </summary>
public double BaseValue { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var line = value as Line;
if (line == null)
return BaseValue;
bool newLine = line != m_curentLine; //check the reference because this method will called twice on one element by my binding
if (newLine)
{
m_lineIndex++;
m_curentLine = line;
}
return BaseValue * m_lineIndex;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I use it in xaml this way
<UserControl.Resources>
<sys:Double x:Key="BusinessRowHeight">22</sys:Double>
<local:LineMultiplierConverter x:Key="LineXConverter" BaseValue="{StaticResource BusinessRowHeight}" />
</UserControl.Resources>
<ItemsControl Grid.Row="1" ItemsSource="{Binding CarBusiness}" Margin="0 5 0 0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line StrokeThickness="1" Stroke="LightGray"
X1="0"
Y1="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource LineXConverter}}"
X2="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}, Path=ActualWidth}"
Y2="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource LineXConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This draws for me a lines for every element in collection with BaseValue offset for X coordinate.
来源:https://stackoverflow.com/questions/22378456/how-to-get-the-index-of-the-current-itemscontrol-item