2013-01-09 2 views
1

UPDATE를 얻을 :은 목록 상자에 항목을 추가하고 ListBoxItem의

내가 분명히 내 문제를 설명하려고 데모를 업로드했습니다. 다운로드하십시오 here.

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에 두 개의 항목이 목록 상자에 추가됩니다 및 selectionManager는 동시에 ListBoxItem의를 얻어야한다. 항목 소스가 ObservableCollection 경우

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

, 당신은 변화에 관여하는 새로운 항목의 목록에 대한 NotifyCollectionChangedEventArgs 확인 NewItems을 가지고 OnCollectionChanged 이벤트를 사용할 수 있습니다.

+0

문제를 설명하기 위해 데모를 올렸습니다. 내 업데이트를 참조하십시오. – Gqqnbig

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

No. 삽입을 사용할 수도 있습니다 – Gqqnbig

+1

@NorbertPisz 질문에 대한 질문과 같이 항목 객체 (예 :'string')에서 실제로 생성 된'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

관련 문제