如何获取当前ItemsControl项的索引?

时间:2014-03-13 12:19:29

标签: c# wpf data-binding itemscontrol

有没有办法获取ItemsControl中当前WPF项的索引?

例如,我想做类似的事情:

<ItemsControl>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding current_index}">
            </TextBox>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

这样,在此之后,第一个TextBox将显示文字"0",第二个"1",第三个"2" ...

5 个答案:

答案 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();
    }
}

结果 enter image description here

答案 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偏移。