WPF Items控制ItemsSource中的当前ListItem索引
是否可以知道ItemsControl中当前项的索引 编辑这很有效WPF Items控制ItemsSource中的当前ListItem索引,wpf,indexing,itemscontrol,Wpf,Indexing,Itemscontrol,是否可以知道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>Thre
<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>
一个
两个
三
看起来是这样的:
是的<代码>项控件公开属性。
ItemContainerGenerator
具有类似于IndexFromContainer
的方法,可用于查找给定项的索引。请注意,如果将ItemsControl
绑定到对象集合,则会自动为每个对象生成一个容器。您可以使用ContainerFromItem
方法找到每个绑定项的容器。我刚才问过同样的问题
没有内置的索引属性,但您可以将ItemsControl的AlternationCount
设置为高于项目计数的值,并绑定到AlternationIndex
<TextBlock Text="{Binding
Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource Mode=TemplatedParent},
FallbackValue=FAIL,
StringFormat={}Index is {0}}" />
需要注意的是,如果您的列表框使用虚拟化作为,则此解决方案可能无法工作。当您使用Alternation Count时,请记住,您还可以将
AlternationCount
属性绑定到要绑定到的集合项的当前计数,因为AlternationCount
是dependencProperty
AlternationCount="{Binding Path=OpeningTimes.Count,FallbackValue='100'}"
希望能有所帮助。这不是一个很好的答案,而是一个建议。不要按照建议使用AlternationIndex技术。它似乎首先起作用,但有严重的副作用。似乎无法保证AlternationIndex从0开始 在第一次渲染时,它可以正常工作 但重新调整网格大小,然后扩展索引中的结果 不再从零开始。您可以在下面的列表中看到效果 形象 这是从以下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>
我正在寻找另一种解决方案:(更可靠的方法是使用值转换器生成带有索引的新集合。使用两个帮助程序,这非常轻松。我使用
IEnumerable.CreateDerivedCollection()
和我为其他目的编写的名为Indexed的帮助程序类
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);
}
}
公共结构索引
{
公共int索引{get;private set;}
公共T值{get;私有集;}
公共索引(int索引,T值):this()
{
指数=指数;
价值=价值;
}
公共重写字符串ToString()
{
return“(索引:“+Index+”,“+Value.ToString()+”);
}
}
公共类索引
{
公共静态索引创建(int索引,T值)
{
返回新的索引(索引,值);
}
}
和转换器
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;
}
}
公共类IndexedConverter:IValueConverter
{
公共对象转换
(对象值)
,类型targetType
,对象参数
,CultureInfo culture
)
{
IEnumerable t=作为IEnumerable的值;
如果(t==null)
{
返回null;
}
IEnumerable e=t.Cast();
int i=0;
返回e.CreateDerivedCollection
(o=>index.Create(i++,o));
}
公共对象转换回(对象值,类型targetType,
对象参数,CultureInfo(区域性)
{
返回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>
一种方法是创建一个自定义的IValueConverter,并将items属性作为参数传递,然后通过查看集合来获取索引,尽管这不是很有效。这也不可靠。如果它是由CollectionViewSource过滤或排序的呢?我承认这很聪明,但有更好的方法。你能在XAML中访问它们吗?不,您不能。如果您需要在没有代码的情况下执行此操作,为什么不使用MVVM模式?创建一个包含其索引的项目列表。因为my CollectionViewSource可能会重新排序或筛选该列表。@ColinE:不幸的是,似乎没有一个好的(内置)在我看来,这确实是最好的方法(因此需要构建自己的包装器),尽管缺少这样的类让我怀疑是否创建了“包含索引的项目列表”是WPF/MVVM设计人员应该采用的方式。这显示了此解决方案的实际效果:干杯。请记住将您的AlternationCount设置为高于items控件中预期的项目数!@Rachel:如果有人想要基于1的索引而不是基于零的索引,您知道解决方案吗?我想我们可以添加一个转换器来增加索引不算什么,只是好奇你是否知道一个更好的方法。我不会这么做。请看我的实验结果以了解发生的错误。嗨,Rachel,仅供参考BradDotNet开发了一个不使用AlternationIndex的不同解决方案。。感谢@LynnCrumbling,很高兴知道其他解决方案:)我认为是虚拟化实现了这一点。如果您有足够的项目需要虚拟化,我不建议您使用AlternationIndex
。您必须尝试看看虚拟化是否可以做到这一点。