[ACCEPTED]-WPF ItemsControl the current ListItem Index in the ItemsSource-itemscontrol
I asked the same thing a while ago here
There 6 isn't a built in Index property, but you 5 can set the AlternationCount
of your ItemsControl to something 4 higher than your item count, and bind to 3 the AlternationIndex
<TextBlock Text="{Binding
Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource Mode=TemplatedParent},
FallbackValue=FAIL,
StringFormat={}Index is {0}}" />
It should be noted that this solution 2 may not work if your ListBox uses Virtualization 1 as bradgonesurfing pointed out here.
This is not quite an answer but a suggestion. Do 13 not use the AlternationIndex technique as 12 suggested. It seems to work first off but 11 there are wierd side effects. It seems that 10 you cannot guarantee that the AlternationIndex 9 starts at 0.
On first rendering it works 8 correctly
but re-sizing the Grid and then 7 expanding results in the index not starting 6 at zero any more. You can see the effect 5 in the below image
This was generated from 4 the following XAML. There are some custom 3 components in there but you will get the 2 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>
I am searching for an alternate solution 1 :(
When you use Alternation Count remember 4 that you can also Bind the AlternationCount
property to 3 the current count of Items of the collection 2 you are binding to since AlternationCount
is a DependencyProperty
.
AlternationCount="{Binding Path=OpeningTimes.Count,FallbackValue='100'}"
Hope it 1 helps.
Yes it is! ItemsControl
exposes an ItemContainerGenerator property. The ItemContainerGenerator
has 6 methods such as IndexFromContainer
which can be used to find 5 the index of a given item. Note that if 4 you bind your ItemsControl
to a collection of objects, a 3 container is automatically generated for 2 each. You can find the container for each 1 bound item using the ContainerFromItem
method.
A more reliable way is to use a value converter 5 to generate a new collection with an index. With 4 a couple of helpers this is pretty painless. I 3 use ReactiveUI's IEnumerable<T>.CreateDerivedCollection()
and a helper class I wrote for other 2 purposes called 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);
}
}
and the converter
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;
}
}
and 1 in the XAML I can do
<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>
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.