2013-06-24 3 views
2

wpf의 ListBox 컨트롤에 대한 사용자 지정 동작을 구현해야합니다. 아이디어는 마지막으로 선택한 요소의 선택을 해제하는 것입니다. 기본 동작에 따라 사용자가 마우스로 선택된 항목을 클릭 할 때 Ctrl 키를 누른 채로 선택하면 선택 항목이 사라집니다. 사용자가 마지막으로 선택한 항목에 마우스 + Ctrl 키를 눌러도 listbox가 아무 작업도 수행하지 못하도록 일부 논리를 구현해야합니다.ListBox에서 마지막으로 선택한 항목을 선택 취소하는 가장 좋은 방법

내가 찾은 유일한 방법은 ListBox.SelectionChanged에 가입 같은 것을하는 것입니다 :

private static void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      var listBox = sender as ListBox; 
      if (listBox != null && e.RemovedItems != null && e.RemovedItems.Count == 1) 
      { 
       var removed = e.RemovedItems[0]; 
       if (listBox.SelectedItems.Count == 0) 
       { 
        if (listBox.SelectionMode == System.Windows.Controls.SelectionMode.Single) 
        { 
         listBox.SelectedItem = removed; 
        } 
        else 
        { 
         listBox.SelectedItems.Add(removed); 
        } 

        e.Handled = true; 
       } 
      } 
     } 

을하지만,이 경우 일부 원하지 않는 통화를 할 때 목록 상자를 발생하기 때문에이 솔루션은 나를 위해 적합하지 않습니다. SelectedItem은 viewmodel 속성에 바인딩됩니다.

의사 콜 스택 (선택 들이지 항목)

  1. 의 selectedItem가되어 selectedItem는 이전 값으로 설정

  2. 라고

  3. listBox_SelectionChanged를 널로 변경

내가 원하는 건 그 단계 야. 1 번과 3 번은 일어나지 않습니다. SelectedItem이 변경되면 일부 장기 실행 비동기 작업이 시작되므로 중요합니다.

고맙습니다. 조언을 부탁드립니다.

답변

1

발견 된 솔루션. ListBox의 PreviewMouseLeftButtonDown 처리가 제대로 작동합니다. 첨부 된 속성으로 제작.

의견 : 문제를 해결할 수 있습니까?

public static class ListBoxAttachedProperties 
    { 
     public static readonly DependencyProperty DisableUnselectLast = 
      DependencyProperty.RegisterAttached(
      "DisableUnselectLast", typeof(bool), typeof(ListBox), 
      new PropertyMetadata(false, DisableUnselectLastChangedCallback)); 

     public static bool GetDisableUnselectLast(DependencyObject d) 
     { 
      return (bool)d.GetValue(DisableUnselectLast); 
     } 

     public static void SetDisableUnselectLast(DependencyObject d, bool value) 
     { 
      d.SetValue(DisableUnselectLast, value); 
     } 

     private static void DisableUnselectLastChangedCallback(
      DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      if (!(d is ListBox)) 
      { 
       return; 
      } 

      var selector = d as ListBox; 
      bool oldValue = (bool)e.OldValue; 
      bool newValue = (bool)e.NewValue; 

      if (oldValue == newValue) 
      { 
       return; 
      } 

      if (oldValue == false) 
      { 
       selector.PreviewMouseLeftButtonDown += listBox_PreviewMouseLeftButtonDown; 
      } 
      else 
      { 
       selector.PreviewMouseLeftButtonDown -= listBox_PreviewMouseLeftButtonDown; 
      } 
     } 

     private static void listBox_PreviewMouseLeftButtonDown(
      object sender, System.Windows.Input.MouseButtonEventArgs e) 
     { 
      var listBox = sender as ListBox; 
      if (listBox != null && listBox.SelectedItems.Count == 1) 
      { 
       UIElement container = listBox.ItemContainerGenerator 
        .ContainerFromItem(listBox.SelectedItems[0]) as UIElement; 

       if (container != null) 
       { 
        var pos = e.GetPosition(container); 
        var result = VisualTreeHelper.HitTest(container, pos); 
        if (result != null) 
        { 
         e.Handled = true; 
        } 
       } 
      } 
     } 
    } 
+0

당신은 제한으로 인해 약 40 분 –

+0

감사합니다 (1 일, 난 괜찮아 경우, 후), 요이치 쿨릭, 난 내 자신의 대답을 받아 질문을 제거하거나 수용으로 답을 표시 할 수 있습니다^__ ^ – garek

관련 문제