有没有办法获取ItemsControl
中当前WPF
项的索引?
例如,我想做类似的事情:
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding current_index}">
</TextBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
这样,在此之后,第一个TextBox
将显示文字"0"
,第二个"1"
,第三个"2" ...
。
答案 0 :(得分:30)
我建议看看:
WPF ItemsControl the current ListItem Index in the ItemsSource
它解释了如何解决ItemsControl上没有内置Index属性的事实。
编辑:
我尝试了以下代码:
<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 >
并获得一个包含三个TextBlocks的窗口,如:
[Index is 0]
[Index is 1]
[Index is 2]
答案 1 :(得分:7)
检查出来
<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>
转换器看起来像这样
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();
}
}
结果
答案 2 :(得分:4)
这是我如何获得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>
转换器:
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");
}
}
通过这种方式,您可以将每种类型的集合绑定到ItemSource,并且他将更改为ListCollectionView。因此转换器将适用于不同的收集类型。
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
答案 3 :(得分:1)
如果您的目标是使ItemTemplate中的按钮正常工作,则可以使用DataContext。您还应该能够使用LINQ从DataContext和ItemsSource中找到索引。
如果使用命令
Command="{Binding DataContext.TestCmd, ElementName=Parent_UC}"
CommandParameter="{Binding DataContext, RelativeSource={RelativeSource Mode=Self}}"
如果使用事件,请使用发送者。
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
if(sender is Button b)
{
if(b.DataContext is ClassType t)
{ enter code here }
}
}
答案 4 :(得分:0)
我是通过计算添加元素索引的转换器完成的。
它仅以一种方式起作用。如果您以某种方式删除项目或更改集合,则应使用其他方法。 而且,您应该为每个集合创建一个单独的转换器,这些元素需要索引。
T
我以这种方式在xaml中使用它
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();
}
}
这为我为集合中的每个元素画了一条线,其中X坐标的BaseValue偏移。