的更新: 的
我上传了一个试图解释我的问题的演示。下载here。
我正在开发一个处理ListBox选择的经理类。 (ListBox提供的默认选择功能不能满足我的要求)
所以,当一个项目被添加到ListBox时,我的经理类应该获得相应的ListBoxItem 并使其被选中或取消选择。
虽然我认为 ItemContainerGenerator.ItemsChanged
应该告诉新添加的项目的一些信息,但是当多次调用ListBox.Items.Add
(使用不同的参数)时,它会提供相同的事件arg,我很困惑。谁能告诉我如何为新添加的项目获取新生成的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;
}
}
}
答案 0 :(得分:0)
如果您的商品来源为ObservableCollection
,则可以使用OnCollectionChanged
事件,其中NotifyCollectionChangedEventArgs
检查NewItems
以查看更改中涉及的新项目列表。
答案 1 :(得分:0)
也许创建自定义列表框类并覆盖方法?
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);
}
}
}
}
答案 2 :(得分:0)
我不确定我是否完全理解这个问题。但是,如果只是关于如何在显示之前操作新创建的ListBoxItem ,则可以创建派生的ListBox并覆盖PrepareContainerForItemOverride方法。
public class MyListBox : ListBox
{
protected override void PrepareContainerForItemOverride(
DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
var listBoxItem = element as ListBoxItem;
...
}
}