将一个项添加到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;
        }
    }
}

将一个项添加到ListBox并获取ListBoxItem

如果您的项目源是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;
        ...
    }
}