将一个项添加到ListBox并获取ListBoxItem
本文关键字:ListBox 获取 ListBoxItem 添加 一个 | 更新日期: 2023-09-27 17:51:03
更新:
我上传了一个演示,试图清楚地解释我的问题。请在此处下载。
我正在开发一个管理器类,用于处理ListBox的选择。(ListBox提供的默认选择功能无法满足我的要求(
因此,当一个项被添加到ListBox时,我的管理器类应该获得相应的ListBoxItem并使其被选中或取消选中。
虽然我认为ItemContainerGenerator.ItemsChanged
应该告诉新添加项目的一些信息,但当ListBox.Items.Add
被多次调用(使用不同的参数(时,它提供了相同的事件参数,这让我很困惑。有人能告诉我如何为新添加的项目获取新生成的ListBoxItem吗。
演示问题的代码:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Button Content="Add two items" Click="Button_Click_1"/>
<ListBox Name="listBox">
<System:Int32>1</System:Int32>
<System:Int32>2</System:Int32>
<System:Int32>3</System:Int32>
</ListBox>
</StackPanel>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SelectionManager selectionManager = new SelectionManager();
selectionManager.Join(listBox);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
listBox.Items.Add(4);
listBox.Items.Add(5);
}
}
在这里,在Button_Click中,两个项目被添加到listBox,selectionManager应该同时获得ListBoxItem。
class SelectionManager
{
public void Join(ListBox element)
{
element.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
}
private List<int> listBoxItemPendingJoinIndexes = new List<int>();
void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
Contract.Requires(listBoxItemPendingJoinIndexes.Count > 0);
ItemContainerGenerator generator = (ItemContainerGenerator)sender;
if (generator.Status != GeneratorStatus.ContainersGenerated)
return;
generator.StatusChanged -= ItemContainerGenerator_StatusChanged;
foreach (var index in listBoxItemPendingJoinIndexes)
{
ListBoxItem listBoxItem = (ListBoxItem)generator.ContainerFromIndex(index);
Join(listBoxItem);
}
listBoxItemPendingJoinIndexes.Clear();
}
void ItemContainerGenerator_ItemsChanged(object sender, ItemsChangedEventArgs e)
{
ItemContainerGenerator generator = (ItemContainerGenerator)sender;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
listBoxItemPendingJoinIndexes.Add(e.Position.Index
+ e.Position.Offset);//same e.Position
generator.StatusChanged += ItemContainerGenerator_StatusChanged;
break;
}
}
}
如果您的项目源是ObservableCollection
,则可以使用OnCollectionChanged
事件,该事件具有NotifyCollectionChangedEventArgs
检查NewItems
以获取更改中涉及的新项目列表。
也许创建一个cutsom列表框类并覆盖这些方法?
public class SafeListBox : ListBox
{
delegate void insertDelegate(int i, object o);
public SafeListBox()
{
this.Items = new CustomObjectCollection(this);
}
public new CustomObjectCollection Items
{
get;
set;
}
public class CustomObjectCollection : ListBox.ObjectCollection
{
private ListBox listBox = null;
public CustomObjectCollection(ListBox listBox) : base(listBox)
{
this.listBox = listBox;
}
public new void Insert(int index, object item)
{
if (listBox.InvokeRequired)
{
insertDelegate setTextDel = delegate(int i, object o)
{
base.Insert(i, o);
};
try
{
listBox.Invoke(setTextDel, new object[] { index, item });
}
catch
{
}
}
else
{
base.Insert(index,item);
}
}
}
}
我不确定我是否完全理解这个问题。但是,如果只是关于如何在新创建的ListBoxItem显示前对其进行一次操作,则可以创建派生的ListBox并重写PrepareContainerForItemOverride方法。
public class MyListBox : ListBox
{
protected override void PrepareContainerForItemOverride(
DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
var listBoxItem = element as ListBoxItem;
...
}
}