WPF ItemsControl el índice actual de ListItem en ItemsSource
indexing (5)
¡Sí lo es! ItemsControl
expone una propiedad ItemContainerGenerator . El ItemContainerGenerator
tiene métodos como IndexFromContainer
que se pueden usar para encontrar el índice de un elemento determinado. Tenga en cuenta que si vincula su ItemsControl
a una colección de objetos, se genera automáticamente un contenedor para cada uno. Puede encontrar el contenedor para cada elemento enlazado utilizando el método ContainerFromItem
.
¿Es posible conocer el índice del ítem actual en un ItemsControl?
EDITAR ¡ Esto funciona!
<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>
Se parece a esto:
Cuando use el recuento de alternativas, recuerde que también puede vincular la propiedad AlternationCount
con el recuento actual de elementos de la colección a la que se está vinculando, ya que AlternationCount
es una propiedad de DependencyProperty
.
AlternationCount="{Binding Path=OpeningTimes.Count,FallbackValue=''100''}"
Espero eso ayude.
Esto no es una respuesta sino una sugerencia. No utilice la técnica AlternationIndex como se sugiere. Parece que funciona primero, pero hay efectos secundarios extraños. Parece que no se puede garantizar que el Índice de Alternancia comience en 0.
En la primera renderización funciona correctamente
pero al cambiar el tamaño de la cuadrícula y luego expandir los resultados en el índice ya no comenzará en cero. Puedes ver el efecto en la imagen de abajo.
Esto se generó a partir del siguiente XAML. Hay algunos componentes personalizados allí pero obtendrás la idea.
<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>
Estoy buscando una solución alternativa :(
Hace un tiempo pregunté lo mismo here
No hay una propiedad de índice integrada, pero puede establecer el recuento de AlternationCount
de su control de elementos en un valor superior a su recuento de elementos y vincularlo al índice de AlternationIndex
<TextBlock Text="{Binding
Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource Mode=TemplatedParent},
FallbackValue=FAIL,
StringFormat={}Index is {0}}" />
Debe tenerse en cuenta que esta solución puede no funcionar si su ListBox utiliza la virtualización como se describe aquí .
Una forma más confiable es usar un convertidor de valores para generar una nueva colección con un índice. Con un par de ayudantes esto es bastante indoloro. Uso IEnumerable<T>.CreateDerivedCollection()
y una clase de ayuda que escribí para otros fines llamados 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);
}
}
y el convertidor
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;
}
}
y en el XAML puedo hacer
<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>