WPF ItemsСогласите текущий индекс ListItem в ItemsSource
Возможно ли узнать текущий элемент Index в элементе ItemsControl?
EDIT Это работает!
<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>
Он выглядит следующим образом:
![enter image description here]()
Ответы
Ответ 1
Я спросил то же самое некоторое время назад здесь
Не существует встроенного свойства Index, но вы можете установить AlternationCount
вашего ItemsControl на нечто большее, чем ваш счетчик элементов, и привязать к AlternationIndex
<TextBlock Text="{Binding
Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource Mode=TemplatedParent},
FallbackValue=FAIL,
StringFormat={}Index is {0}}" />
Следует отметить, что это решение может не работать, если ваш ListBox использует виртуализацию как bradgonesurfing, указанный здесь.
Ответ 2
Когда вы используете Alternation Count помните, что вы также можете привязать свойство AlternationCount
к текущему счету элементов коллекции, с которой вы привязываетесь, поскольку AlternationCount
- это DependencyProperty
.
AlternationCount="{Binding Path=OpeningTimes.Count,FallbackValue='100'}"
Надеюсь, что это поможет.
Ответ 3
Это не совсем ответ, а предложение. Не используйте технику AlternationIndex, как было предложено. Кажется, что он работает сначала, но есть более серьезные побочные эффекты. Кажется, что вы не можете гарантировать, что AlternationIndex начинается с 0.
При первом рендеринге он работает правильно
![enter image description here]()
но переопределяя Grid и затем расширяя результаты в индексе
не начинать с нуля. Вы можете увидеть эффект в нижнем
Изображение
![enter image description here]()
Это было создано из следующего 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>
Я ищу альтернативное решение: (
Ответ 4
Да, это так! ItemsControl
предоставляет свойство ItemContainerGenerator. ItemContainerGenerator
имеет методы, такие как IndexFromContainer
, которые можно использовать для поиска индекса данного элемента. Обратите внимание: если вы привяжете свой ItemsControl
к коллекции объектов, контейнер будет автоматически сгенерирован для каждого. Контейнер для каждого связанного элемента можно найти с помощью метода ContainerFromItem
.
Ответ 5
Более надежным способом является использование преобразователя значений для генерации новой коллекции с индексом. С помощью нескольких помощников это довольно безболезненно. Я использую ReactiveUI IEnumerable<T>.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);
}
}
и преобразователь
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>