是否可以在ItemsControl中知道当前项目的索引?
编辑这有效!
<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>
<StackPanel Margin="10">
<!-- one -->
<TextBlock Text="{Binding Path=.,
StringFormat={}Value is {0}}" />
<!-- two -->
<TextBlock Text="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource TemplatedParent},
FallbackValue=FAIL,
StringFormat={}Index is {0}}" />
<!-- three -->
<TextBlock Text="{Binding Path=Items.Count,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}},
StringFormat={}Total is {0}}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
看起来像这样:
答案 0 :(得分:22)
前一段时间我问了同样的问题here
没有内置的索引属性,但您可以将ItemsControl的AlternationCount
设置为高于项目数的值,并绑定到AlternationIndex
<TextBlock Text="{Binding
Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource Mode=TemplatedParent},
FallbackValue=FAIL,
StringFormat={}Index is {0}}" />
应该注意的是,如果您的ListBox使用虚拟化为bradgonesurfing pointed out here,则此解决方案可能无效。
答案 1 :(得分:8)
这不是一个答案,而是一个建议。不要使用建议的AlternationIndex技术。它似乎首先起作用,但有副作用。您似乎无法保证AlternationIndex从0开始。
首次渲染时,它可以正常工作
但重新调整Grid的大小,然后在索引中扩展结果 不再从零开始。你可以在下面看到效果 图像
这是从以下XAML生成的。那里有一些自定义组件,但你会明白这一点。
<DataGrid
VirtualizingPanel.VirtualizationMode="Recycling"
ItemsSource="{Binding MoineauPumpFlanks.Stator.Flank.Boundary, Mode=OneWay}"
AlternationCount="{Binding MoineauPumpFlanks.Stator.Flank.Boundary.Count, Mode=OneWay}"
AutoGenerateColumns="False"
HorizontalScrollBarVisibility="Hidden"
>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Id">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock
Margin="0,0,5,0"
TextAlignment="Right"
Text="{Binding RelativeSource={ RelativeSource
Mode=FindAncestor,
AncestorType=DataGridRow},
Path=AlternationIndex}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn >
<DataGridTemplateColumn.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Point ["/>
<Controls:DisplayUnits DisplayUnitsAsAbbreviation="True" DisplayUnitsMode="Length"/>
<TextBlock Text="]"/>
</StackPanel>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Controls:LabelForPoint ShowUnits="False" Point="{Binding}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
我正在寻找替代解决方案:(
答案 2 :(得分:6)
当您使用轮换计数时,请记住您还可以将AlternationCount
属性绑定到您绑定到的集合的项目的当前计数,因为AlternationCount
是DependencyProperty
。
AlternationCount="{Binding Path=OpeningTimes.Count,FallbackValue='100'}"
希望它有所帮助。
答案 3 :(得分:1)
是的! ItemsControl
公开ItemContainerGenerator属性。 ItemContainerGenerator
具有IndexFromContainer
等方法,可用于查找给定项目的索引。请注意,如果将ItemsControl
绑定到对象集合,则会自动为每个对象生成一个容器。您可以使用ContainerFromItem
方法找到每个绑定项的容器。
答案 4 :(得分:0)
更可靠的方法是使用值转换器生成带索引的新集合。有几个帮手,这是非常轻松的。我使用ReactiveUI's IEnumerable<T>.CreateDerivedCollection()
和我为其他目的编写的帮助类,称为索引。
public struct Indexed<T>
{
public int Index { get; private set; }
public T Value { get; private set; }
public Indexed(int index, T value) : this()
{
Index = index;
Value = value;
}
public override string ToString()
{
return "(Indexed: " + Index + ", " + Value.ToString () + " )";
}
}
public class Indexed
{
public static Indexed<T> Create<T>(int indexed, T value)
{
return new Indexed<T>(indexed, value);
}
}
和转换器
public class IndexedConverter : IValueConverter
{
public object Convert
( object value
, Type targetType
, object parameter
, CultureInfo culture
)
{
IEnumerable t = value as IEnumerable;
if ( t == null )
{
return null;
}
IEnumerable<object> e = t.Cast<object>();
int i = 0;
return e.CreateDerivedCollection<object, Indexed<object>>
(o => Indexed.Create(i++, o));
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return null;
}
}
在XAML中我可以做到
<DataGrid
VirtualizingPanel.VirtualizationMode="Recycling"
ItemsSource="{Binding
MoineauPumpFlanks.Stator.Flank.Boundary,
Mode=OneWay,
Converter={StaticResource indexedConverter}}"
AutoGenerateColumns="False"
HorizontalScrollBarVisibility="Hidden"
>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Id">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!-- Get the index of Indexed<T> -->
<TextBlock
Margin="0,0,5,0"
TextAlignment="Right"
Text="{Binding Path=Index}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Point" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!-- Get the value of Indexed<T> -->
<TextBlock Content="{Binding Value}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>