2013-01-09 86 views
1

UPDATE:項目添加到列表框,並得到一個ListBoxItem

我上傳了演示試圖解釋我的問題清楚。下載它here

我正在開發一個處理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,兩個項目被添加到列表框,並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

@Soner是的,我更新了。請檢查。 – Gqqnbig

+0

你對「同樣的e.Position」的評論是否也意味着「同樣的e.Offset」?也許[這個博客](http://blogs.msdn.com/b/dancre/archive/2006/02/13/implementing-a-virtualizingpanel-part-2-iitemcontainergenerator.aspx)是有幫助的。你真的在每個「Add」上附加一個'StatusChanged'處理程序嗎? 「Join(listBoxItem)」做什麼? – Clemens

回答

0

也許創建一個fragom listbox類並重寫方法?

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); 
       } 
      } 
     } 
    } 
+0

No ..我也可以使用插入 – Gqqnbig

+1

@NorbertPisz你如何從一個項目對象(例如一個'字符串)生成的'ListBoxItem'按照問題的要求? – Clemens

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; 
     ... 
    } 
} 
+0

我上傳了一個演示,試圖清楚地解釋我的問題。查看我的更新。 – Gqqnbig

相關問題