WPF-从ItemsControl的ItemTemplate中绑定到Item索引?
有没有办法从ItemsControl的ItemTemplate中绑定到ItemIndex 例如:WPF-从ItemsControl的ItemTemplate中绑定到Item索引?,wpf,data-binding,itemscontrol,Wpf,Data Binding,Itemscontrol,有没有办法从ItemsControl的ItemTemplate中绑定到ItemIndex 例如: <ItemsControl ItemsSource="{Binding Path=ItemList}"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Path=ThisItemsIndex}" />
<ItemsControl ItemsSource="{Binding Path=ItemList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=ThisItemsIndex}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
如果您没有使用任何类型的交替行样式,您可能会为此劫持AlternationIndex。将ItemsControl上的AlternationCount设置为大于项目最大可能计数的值,然后使用
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(ItemsControl.AlternationIndex)}"
编辑:因为,如果您使用虚拟化,则不建议这样做,因为它只会对生成的项目进行索引,而不会对整个列表进行索引。对于记录,还有另一种方法可以实现这一点:使用自定义转换器。稍微复杂一点,但您不必担心AlternationCount/Index
public sealed class ArrayWrapperConverter : IValueConverter
{
private static readonly Type ArrayWrappingHelperType = typeof(ArrayWrappingHelper<>);
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return null;
}
Type valueType = value.GetType();
if (!valueType.IsArray)
{
return DependencyProperty.UnsetValue;
}
Type elementType = valueType.GetElementType();
Type specificType = ArrayWrappingHelperType.MakeGenericType(elementType);
IEnumerable wrappingHelper = (IEnumerable) Activator.CreateInstance(specificType, value);
return wrappingHelper;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
internal class ArrayWrappingHelper<TValue> : IEnumerable
{
private readonly TValue[] _array;
public ArrayWrappingHelper(object array)
{
_array = (TValue[]) array;
}
public IEnumerator GetEnumerator()
{
return _array.Select((item, index) => new ArrayItemWrapper<TValue>(_array, index)).GetEnumerator();
}
}
public class ArrayItemWrapper<TValue>
{
private readonly TValue[] _array;
private readonly int _index;
public int Index
{
get { return _index; }
}
public TValue Value
{
get { return _array[_index]; }
set { _array[_index] = value; }
}
public ArrayItemWrapper(TValue[] array, int index)
{
_array = array;
_index = index;
}
}
公共密封类ArrayWrapperConverter:IValueConverter
{
私有静态只读类型ArrayRappingHelperType=typeof(ArrayRappingHelper);
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
如果(值==null)
{
返回null;
}
类型valueType=value.GetType();
如果(!valueType.IsArray)
{
返回dependencProperty.unset值;
}
Type elementType=valueType.GetElementType();
类型specificType=ArrayRappingHelperType.MakeGenericType(elementType);
IEnumerable wrappingHelper=(IEnumerable)Activator.CreateInstance(specificType,value);
返回包装器;
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
内部类ArrayRappingHelper:IEnumerable
{
专用只读TValue[]_数组;
公共数组rappingHelper(对象数组)
{
_数组=(TValue[])数组;
}
公共IEnumerator GetEnumerator()
{
返回_数组。选择((项,索引)=>new ArrayItemWrapper(_数组,索引)).GetEnumerator();
}
}
公共类ArrayItemWrapper
{
专用只读TValue[]_数组;
私有只读int_索引;
公共整数索引
{
获取{return_index;}
}
公共价值
{
获取{return _数组[_索引];}
集合{u数组[\u索引]=value;}
}
公共ArrayItemWrapper(TValue[]数组,int索引)
{
_数组=数组;
_指数=指数;
}
}
示例用法:
<Window x:Class="WpfArrayBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c="clr-namespace:WpfArrayBinding.Converters"
xmlns:s="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<c:ArrayWrapperConverter x:Key="ArrayWrapperConverter" />
<x:Array Type="{x:Type s:String}" x:Key="MyArray">
<s:String>Foo</s:String>
<s:String>Bar</s:String>
<s:String>Baz</s:String>
</x:Array>
</ResourceDictionary>
</Window.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource MyArray}, Converter={StaticResource ArrayWrapperConverter}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Index}" />
<TextBox Text="{Binding Value}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
福
酒吧
巴兹
以下是我用来在集合项上添加可绑定索引的方法。我基本上是将我的项目包装在一个有索引的容器中,并有一个接受包装的自定义ObservableCollection
请注意,MoveItem不会被覆盖,但必须被覆盖才能完整实现
public class IndexedItemContainerCollection<T> : ObservableCollection<IndexedItemContainer<T>>
{
public IndexedItemContainerCollection()
{
}
public IndexedItemContainerCollection(IEnumerable<IndexedItemContainer<T>> collection)
: base(collection)
{
var index = 0;
foreach (var item in this)
{
item.Index = index;
}
}
protected override void InsertItem(int index, IndexedItemContainer<T> item)
{
item.Index = index;
base.InsertItem(index, item);
foreach (var indexedItem in this.Where(x=>x.Index > index))
{
indexedItem.Index++;
}
}
protected override void RemoveItem(int index)
{
base.RemoveItem(index);
foreach (var indexedItem in this.Where(x => x.Index > index))
{
indexedItem.Index--;
}
}
}
public class IndexedItemContainer<T>
{
public int Index { get; set; }
public T Item { get; set; }
}
公共类IndexedItemContainerCollection:ObservableCollection
{
公共IndexedeMContainerCollection()
{
}
公共IndexedItemContainerCollection(IEnumerable集合)
:基本(集合)
{
var指数=0;
foreach(本文件中的var项目)
{
项目索引=索引;
}
}
受保护的重写void插入项(int索引,IndexedItemContainer项)
{
项目索引=索引;
基本插入项(索引,项目);
foreach(在这个.Where(x=>x.Index>Index)中的var indexedItem)
{
Index++;
}
}
受保护的覆盖void removietem(int索引)
{
基本删除项(索引);
foreach(在这个.Where(x=>x.Index>Index)中的var indexedItem)
{
indexedItem.Index;
}
}
}
公共类IndexedItemContainer
{
公共int索引{get;set;}
公共T项{get;set;}
}
然后,我扩展包装器类以获得一个可绑定属性,我可以控制索引的显示方式:
public class NamedIndexedItemContainer<T> : IndexedItemContainer<T>
{
public string Name
{
get { return string.Format("Item #{0}", Index + 1); }
}
}
公共类名称dIndexEditemContainer:IndexedItemContainer
{
公共字符串名
{
获取{return string.Format(“Item{0}”,Index+1)}
}
}
示例用法
XAML:
代码:
private IndexedItemContainerCollection\u itemList;
公共IndexedItemContainerCollection项目列表
{
获取{return\u itemList;}
设置{u itemList=value;OnPropertyChanged();}
}
ItemList=新的IndexedItemContainerCollection();
var newItem=new NamedIndexedItemContainer(){Item=new MyItem(){…}};
ItemList.Add(newItem);
当然,与实际MyItem实例的任何绑定都必须通过IndexedeTemContainer的Item属性。谢谢,下次我需要ItemsControl中的ItemIndex时,我必须尝试一下:)您在使用此属性时有任何性能问题吗?没有,但是我只在相对较小的数组中使用它。谢谢。我通常不喜欢从
ObservaleCollection
继承,但是如果将来需要类似的东西,我会记住这一点:)不要这样做。请参阅“帮助”,但它从0开始,除非UI是为程序员设计的,否则它不是很有用。我想大多数想要这个的人都希望它从1开始。
<ComboBox ItemsSource="{Binding ItemList}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
private IndexedItemContainerCollection<MyItem> _itemList;
public IndexedItemContainerCollection<MyItem> ItemList
{
get { return _itemList; }
set { _itemList= value; OnPropertyChanged(); }
}
ItemList = new IndexedItemContainerCollection<MyItem>();
var newItem = new NamedIndexedItemContainer<MyItem>() { Item = new MyItem() { ... } };
ItemList.Add(newItem);