2014-02-24 4 views
0

클릭 한 항목의 색인을 얻기 위해 아래의 GetListBoxItemIndex 함수를 구현하는 방법은 무엇입니까? 내가 성공하지 VisualTreeHelper를 사용하여 시도 (의미, VisualTreeHelper 분명히 작동하지만, 나는 ... 트리 검색을 어디받지 못했습니다) 그것 때문에SelectedIndex 등을 사용하지 않고 ListBox 항목의 색인을 얻는 방법 (PreviewMouseDown에서 아직 아무것도 선택되지 않았습니다.)

private void MyListBox_OnPreviewMouseDown(object sender, MouseButtonEventArgs e){ 
    var listBox = sender as ListBox; 
    var src = e.OriginalSource as DependencyObject; 
    if (src == null || listBox == null) return; 

    var i = GetListBoxItemIndex(listBox,src); 

    DragDrop.DoDragDrop(src, BoundCollection[i], DragDropEffects.Copy); 
    // BoundCollection defined as: 
    // ObservableCollection<SomeDataModelType> BoundCollection 
} 

는,이 상태에서 아직 선택 아무것도 없다는 것을 유의하시기 바랍니다 PreviewMouseDown 이벤트

답변

3

단계는 코멘트에, 당신은 문제를 해결하는 데 도움이 될 것입니다 다음 코드,

private void ListBox_OnPreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    // you can check which mouse button, its state, or use the correct event. 

    // get the element the mouse is currently over 
    var uie = ListBox.InputHitTest(Mouse.GetPosition(this.ListBox)); 

    if (uie == null) 
     return; 

    // navigate to its ListBoxItem container 
    var listBoxItem = FindParent<ListBoxItem>((FrameworkElement) uie); 

    // in case the click was not over a listBoxItem 
    if (listBoxItem == null) 
     return; 

    // here is the index 
    int index = this.ListBox.ItemContainerGenerator.IndexFromContainer(listBoxItem); 
    MessageBox.Show(index.ToString()); 
} 

public static T FindParent<T>(FrameworkElement child) where T : DependencyObject 
{ 
    T parent = null; 
    var currentParent = VisualTreeHelper.GetParent(child); 

    while (currentParent != null) 
    { 

     // check the current parent 
     if (currentParent is T) 
     { 
      parent = (T)currentParent; 
      break; 
     } 

     // find the next parent 
     currentParent = VisualTreeHelper.GetParent(currentParent); 
    } 

    return parent; 
} 

업데이트

원하는 것은 클릭 한 데이터 항목의 색인입니다. 컨테이너를 가져 오면 DataContext을 통해 연결된 데이터 항목을 가져올 때까지 인덱스를 가져올 수 없으며 바운드 컬렉션에서 인덱스를 찾습니다. ItemContainerGenerator이 이미 해당 작업을 수행합니다.

코드에서 ListBoxItem 인덱스가 바운드 컬렉션의 데이터 항목의 동일한 인덱스라고 가정 할 경우 Virtualization이 꺼져있는 경우에만 해당됩니다. 이 속성이 켜져 있으면 표시 영역의 항목에 대한 컨테이너 만 인스턴스화됩니다. 예를 들어, 바운드 컬렉션에 1000 개의 데이터 항목이 있고 50 번째 데이터 항목으로 스크롤 한 경우 이론적으로 인덱스 0에있는 ListBoxItem은 50 번째 데이터 항목에 바인딩되어 있으므로 가정이 잘못되었음을 증명합니다.

키보드 탐색이 제대로 작동하려면 Virtualization이 켜져있을 때 스크롤 영역의 위쪽과 아래쪽에 숨겨진 컨테이너가 만들어져 이론적으로 앞서 말한 적이 있습니다.

+0

감사합니다. 작동합니다. 하지만 왜 'ItemContainerGenerator'가 필요한지 설명 할 수 있습니까? 왜 아이템을 가져 오기 위해 "tree-walk"('VisualTreeHelper' 메소드) 할 수 없습니까? – Tar

+0

업데이트를 살펴보십시오. – abdelkarim