将项添加到ListBox并获取ListBoxItem

时间:2013-01-09 14:57:40

标签: c# wpf listbox

更新:

我上传了一个试图解释我的问题的演示。下载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;
        }

    }
}

3 个答案:

答案 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;
        ...
    }
}