有一种方法可以在不使用转换器的情况下实现这一点,并且具有在集合中具有重复项的能力,但这意味着您必须使用 KeyValuePair<int, T>
作为列表项类型来维护组织良好的列表并存储索引。
这里是一个字符串列表的示例实现。它将显示按钮内部的文本,并将索引绑定到命令参数:
#region Items
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items", typeof(ObservableCollection<string>), typeof(CulturePicker),
new FrameworkPropertyMetadata(new ObservableCollection<string>(),
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(OnItemsChanged)));
public ObservableCollection<string> Items
{
get { return (ObservableCollection<string>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
private static void OnItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CulturePicker _this = (CulturePicker)d;
ObservableCollection<string> oldItems = (ObservableCollection<string>)e.OldValue;
ObservableCollection<string> newItems = _this.Items;
if (oldItems != null)
{
oldItems.CollectionChanged -= this.Items_CollectionChanged;
}
List<KeyValuePair<int, string>> organizedItems = new List<KeyValuePair<int, string>>();
for (int i = 0; i < newItems.Count; i++)
{
organizedItems.Add(new KeyValuePair<int, string>(i, newItems[i]));
}
this.OrganizedItems = organizedItems;
newItems.CollectionChanged += this.Items_CollectionChanged;
}
private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
List<KeyValuePair<int, string>> organizedItems = new List<KeyValuePair<int, string>>();
for (int i = 0; i < e.NewItems.Count; i++)
{
organizedItems.Add(new KeyValuePair<int, string>(i, (string)e.NewItems[i]));
}
this.OrganizedItems = organizedItems;
}
#endregion
#region OrganizedItems
private static readonly DependencyProperty OrganizedItemsProperty =
DependencyProperty.Register("OrganizedItems", typeof(List<KeyValuePair<int, string>>), typeof(CulturePicker),
new FrameworkPropertyMetadata((List<KeyValuePair<int, string>>)null,
FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(OnOrganizedItemsChanged)));
private List<KeyValuePair<int, string>> OrganizedItems
{
get { return (List<KeyValuePair<int, string>>)GetValue(OrganizedItemsProperty); }
set { SetValue(OrganizedItemsProperty, value); }
}
private static void OnOrganizedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CulturePicker _this = (CulturePicker)d;
List<KeyValuePair<int, string>> oldOrganizedItems = (List<KeyValuePair<int, string>>)e.OldValue;
List<KeyValuePair<int, string>> newOrganizedItems = _this.OrganizedItems;
}
#endregion
<UserControl ...
Name="_">
...
<ItemsControl ItemsSource="{Binding OrganizedItems, ElementName=_}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding Command, ElementName=_}"
CommandParameter="{Binding Key}"
Text="{Binding Value}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
...
在XAML中,Key是索引,Value是实际项,本例中为字符串。此示例未包含
Command
属性。另请注意,任何更改源列表都将重新创建有序列表,这将触发重新渲染并导致大型列表变慢。