2010-05-19 3 views
7

누구든지이 작업을 수행하는 방법에 대한 아이디어가 있는지 궁금 할 것입니다. 사용자가 마우스를 클릭하고 드래그하여 여러 항목을 선택할 수있게하고 싶습니다. 사용자가 항목 1을 클릭 한 다음 항목 10으로 아래로 끕니다. 1 번 항목을 클릭 한 다음 10 번 항목을 Shift + 클릭 한 것처럼 1 번부터 10 번 항목을 선택해야합니다.wpf listview 여러 항목을 선택하여 끌기

감사합니다.

+0

, 나중에 솔루션을 게시합니다. 감사. – Carlo

+0

나는이 질문에 대한 새로운 솔루션을 [WPF 드래그 앤 드롭으로 ListBox에서 SelectionMode Multiple] (http://stackoverflow.com/questions/1553622/wpf-drag-drop-from-listbox-with-selectionmode)에 게시했습니다. -배수). –

답변

9

내 솔루션은 ListView의 PreviewLeftMouseButtonDown 및 MouseLeftButtonUp을 처리하는 도우미 클래스를 만들고 ListViewItems의 작은 스타일은 마우스를 가리면 헬퍼 클래스를 나타내므로 선택 여부를 결정할 수 있습니다. 항목 (마우스 왼쪽 버튼을 누르거나 누르지 않았을 때).

XAML :

<Window x:Class="DragSelectListBox.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:DragSelectListBox" 
    Title="Window1" Height="300" Width="300"> 
    <Window.Resources> 

     <Style TargetType="{x:Type ListBoxItem}"> 
      <Setter Property="local:DragSelectionHelper.IsDragSelecting" Value="False" /> 
      <Style.Triggers> 
       <Trigger Property="ListBoxItem.IsMouseOver" Value="True"> 
        <Setter Property="local:DragSelectionHelper.IsDragSelecting" Value="True" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 

    </Window.Resources> 

    <Grid Background="AliceBlue"> 
     <ListBox Margin="8" 
       local:DragSelectionHelper.IsDragSelectionEnabled="true"> 
      <ListBoxItem Content="Item 1" /> 
      <ListBoxItem Content="Item 2" /> 
      <ListBoxItem Content="Item 3" /> 
      <ListBoxItem Content="Item 4" /> 
      <ListBoxItem Content="Item 5" /> 
      <ListBoxItem Content="Item 6" /> 
      <ListBoxItem Content="Item 7" /> 
      <ListBoxItem Content="Item 8" /> 
      <ListBoxItem Content="Item 9" /> 
      <ListBoxItem Content="Item 10" /> 
      <ListBoxItem Content="Item 11" /> 
      <ListBoxItem Content="Item 12" /> 
      <ListBoxItem Content="Item 13" /> 
      <ListBoxItem Content="Item 14" /> 
      <ListBoxItem Content="Item 15" /> 
      <ListBoxItem Content="Item 16" /> 
      <ListBoxItem Content="Item 17" /> 
      <ListBoxItem Content="Item 18" /> 
      <ListBoxItem Content="Item 19" /> 
      <ListBoxItem Content="Item 20" /> 
      <ListBoxItem Content="Item 21" /> 
      <ListBoxItem Content="Item 22" /> 
      <ListBoxItem Content="Item 23" /> 
      <ListBoxItem Content="Item 24" /> 
      <ListBoxItem Content="Item 25" /> 
      <ListBoxItem Content="Item 26" /> 
      <ListBoxItem Content="Item 27" /> 
      <ListBoxItem Content="Item 28" /> 
      <ListBoxItem Content="Item 29" /> 
      <ListBoxItem Content="Item 30" /> 
     </ListBox> 
    </Grid> 
</Window> 

C 번호 : 당신이 볼 수 그래서

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 

namespace DragSelectListBox 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
     } 
    } 

    // CARLO 20100519: Helper class for DragSelection 
    public class DragSelectionHelper : DependencyObject 
    { 
     #region Random Static Properties 

     // need a static reference to the listbox otherwise it can't be accessed 
      // (this only happened in the project I'm working on, if you're using a regular ListBox, with regular ListBoxItems you can get the ListBox from the ListBoxItems) 
     public static ListBox ListBox { get; private set; } 

     #endregion Random Static Properties 

     #region IsDragSelectionEnabledProperty 

     public static bool GetIsDragSelectionEnabled(DependencyObject obj) 
     { 
      return (bool)obj.GetValue(IsDragSelectionEnabledProperty); 
     } 

     public static void SetIsDragSelectionEnabled(DependencyObject obj, bool value) 
     { 
      obj.SetValue(IsDragSelectionEnabledProperty, value); 
     } 

     public static readonly DependencyProperty IsDragSelectionEnabledProperty = 
      DependencyProperty.RegisterAttached("IsDragSelectingEnabled", typeof(bool), typeof(DragSelectionHelper), new UIPropertyMetadata(false, IsDragSelectingEnabledPropertyChanged)); 

     public static void IsDragSelectingEnabledPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
     { 
      ListBox listBox = o as ListBox; 

      bool isDragSelectionEnabled = DragSelectionHelper.GetIsDragSelectionEnabled(listBox); 

      // if DragSelection is enabled 
      if (isDragSelectionEnabled) 
      { 
       // set the listbox's selection mode to multiple (didn't work with extended) 
       listBox.SelectionMode = SelectionMode.Multiple; 

       // set the static listbox property 
       DragSelectionHelper.ListBox = listBox; 

       // and subscribe to the required events to handle the drag selection and the attached properties 
       listBox.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(DragSelectionHelper.listBox_PreviewMouseLeftButtonDown); 
       listBox.PreviewMouseRightButtonDown += new MouseButtonEventHandler(listBox_PreviewMouseRightButtonDown); 
       listBox.MouseLeftButtonUp += new MouseButtonEventHandler(DragSelectionHelper.listBox_MouseLeftButtonUp); 
      } 
      else // is selection is disabled 
      { 
       // set selection mode to the default 
       listBox.SelectionMode = SelectionMode.Single; 

       // dereference the listbox 
       DragSelectionHelper.ListBox = null; 

       // unsuscribe from the events 
       listBox.PreviewMouseLeftButtonDown -= new MouseButtonEventHandler(DragSelectionHelper.listBox_PreviewMouseLeftButtonDown); 
       listBox.MouseLeftButtonUp -= new MouseButtonEventHandler(DragSelectionHelper.listBox_MouseLeftButtonUp); 
       listBox.MouseLeftButtonUp -= new MouseButtonEventHandler(DragSelectionHelper.listBox_MouseLeftButtonUp); 
      } 
     } 

     static void listBox_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) 
     { 
      // to prevent the listbox from selecting/deselecting wells on right click 
      e.Handled = true; 
     } 

     private static void listBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
     { 
      // notify the helper class that the listbox has initiated the drag click 
      DragSelectionHelper.SetIsDragClickStarted(DragSelectionHelper.ListBox, true); 
     } 

     private static void listBox_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
     { 
      // notify the helper class that the list box has terminated the drag click 
      DragSelectionHelper.SetIsDragClickStarted(DragSelectionHelper.ListBox, false); 
     } 

     #endregion IsDragSelectionEnabledProperty 

     #region IsDragSelectinProperty 

     public static bool GetIsDragSelecting(DependencyObject obj) 
     { 
      return (bool)obj.GetValue(IsDragSelectingProperty); 
     } 

     public static void SetIsDragSelecting(DependencyObject obj, bool value) 
     { 
      obj.SetValue(IsDragSelectingProperty, value); 
     } 

     public static readonly DependencyProperty IsDragSelectingProperty = 
      DependencyProperty.RegisterAttached("IsDragSelecting", typeof(bool), typeof(DragSelectionHelper), new UIPropertyMetadata(false, IsDragSelectingPropertyChanged)); 

     public static void IsDragSelectingPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
     { 
      ListBoxItem item = o as ListBoxItem; 

      bool clickInitiated = DragSelectionHelper.GetIsDragClickStarted(DragSelectionHelper.ListBox); 

      // this is where the item.Parent was null, it was supposed to be the ListBox, I guess it's null because items are not 
      // really ListBoxItems but are wells 
      if (clickInitiated) 
      { 
       bool isDragSelecting = DragSelectionHelper.GetIsDragSelecting(item); 

       if (isDragSelecting) 
       { 
        // using the ListBox static reference because could not get to it through the item.Parent property 
        DragSelectionHelper.ListBox.SelectedItems.Add(item); 
       } 
      } 
     } 

     #endregion IsDragSelectinProperty 

     #region IsDragClickStartedProperty 

     public static bool GetIsDragClickStarted(DependencyObject obj) 
     { 
      return (bool)obj.GetValue(IsDragClickStartedProperty); 
     } 

     public static void SetIsDragClickStarted(DependencyObject obj, bool value) 
     { 
      obj.SetValue(IsDragClickStartedProperty, value); 
     } 

     public static readonly DependencyProperty IsDragClickStartedProperty = 
      DependencyProperty.RegisterAttached("IsDragClickStarted", typeof(bool), typeof(DragSelectionHelper), new UIPropertyMetadata(false, IsDragClickStartedPropertyChanged)); 

     public static void IsDragClickStartedPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
     { 
      bool isDragClickStarted = DragSelectionHelper.GetIsDragClickStarted(DragSelectionHelper.ListBox); 

      // if click has been drag click has started, clear the current selected items and start drag selection operation again 
      if (isDragClickStarted) 
       DragSelectionHelper.ListBox.SelectedItems.Clear(); 
     } 

     #endregion IsDragClickInitiatedProperty 
    } 
} 

, 당신이해야 할 모든 당신의 XAML에서 스타일을 추가하고, 세트 어쨌든, 여기에 전체 프로젝트의 :

지역 : 패에 DragSelectionHelper.IsDragSelectionEnabled = "true"로

연결된 속성 istView, 그리고 그것은 모든 것을 다룰 것입니다.

감사합니다.

2

SelectionMode=Extended으로 사용자가 마우스 버튼을 누르기 전에 SHIFT 키를 누르고있는 경우 이미 가능합니다.

2

Carlo의 대답에 따라 코드 일부가 수정되었으므로 CTRL을 사용하여 현재 선택을 지우지 않고 계속 선택하고 SHIFT를 사용하여 '확장'모드와 같은 항목을 선택할 수 있습니다.

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Controls.Primitives; 
using System.Windows.Input; 
using System.Windows.Media; 

namespace SteamFriendsManager.Utility 
{ 
    public class DragSelectionHelper : DependencyObject 
    { 
     #region IsDragSelectionEnabledProperty 

     public static bool GetIsDragSelectionEnabled(DependencyObject obj) 
     { 
      return (bool) obj.GetValue(IsDragSelectionEnabledProperty); 
     } 

     public static void SetIsDragSelectionEnabled(DependencyObject obj, bool value) 
     { 
      obj.SetValue(IsDragSelectionEnabledProperty, value); 
     } 

     public static readonly DependencyProperty IsDragSelectionEnabledProperty = 
      DependencyProperty.RegisterAttached("IsDragSelectingEnabled", typeof (bool), typeof (DragSelectionHelper), 
       new UIPropertyMetadata(false, IsDragSelectingEnabledPropertyChanged)); 

     private static void IsDragSelectingEnabledPropertyChanged(DependencyObject o, 
      DependencyPropertyChangedEventArgs e) 
     { 
      var listBox = o as ListBox; 

      if (listBox == null) 
       return; 

      // if DragSelection is enabled 
      if (GetIsDragSelectionEnabled(listBox)) 
      { 
       // set the listbox's selection mode to multiple (didn't work with extended) 
       listBox.SelectionMode = SelectionMode.Multiple; 

       // and subscribe to the required events to handle the drag selection and the attached properties 
       listBox.PreviewMouseRightButtonDown += listBox_PreviewMouseRightButtonDown; 

       listBox.PreviewMouseLeftButtonDown += listBox_PreviewMouseLeftButtonDown; 
       listBox.PreviewMouseLeftButtonUp += listBox_PreviewMouseLeftButtonUp; 

       listBox.PreviewKeyDown += listBox_PreviewKeyDown; 
       listBox.PreviewKeyUp += listBox_PreviewKeyUp; 
      } 
      else // is selection is disabled 
      { 
       // set selection mode to the default 
       listBox.SelectionMode = SelectionMode.Extended; 

       // unsuscribe from the events 
       listBox.PreviewMouseRightButtonDown -= listBox_PreviewMouseRightButtonDown; 

       listBox.PreviewMouseLeftButtonDown -= listBox_PreviewMouseLeftButtonDown; 
       listBox.PreviewMouseLeftButtonUp -= listBox_PreviewMouseLeftButtonUp; 

       listBox.PreviewKeyDown -= listBox_PreviewKeyDown; 
       listBox.PreviewKeyUp += listBox_PreviewKeyUp; 
      } 
     } 

     private static void listBox_PreviewKeyDown(object sender, KeyEventArgs e) 
     { 
      var listBox = sender as ListBox; 
      if (listBox == null) 
       return; 

      if (e.Key == Key.LeftShift || e.Key == Key.RightShift) 
      { 
       SetIsDragSelectionEnabled(listBox, false); 
      } 
     } 

     private static void listBox_PreviewKeyUp(object sender, KeyEventArgs e) 
     { 
      var listBox = sender as ListBox; 
      if (listBox == null) 
       return; 

      if (e.Key == Key.LeftShift || e.Key == Key.RightShift) 
      { 
       SetIsDragSelectionEnabled(listBox, true); 
      } 
     } 

     private static void listBox_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) 
     { 
      // to prevent the listbox from selecting/deselecting wells on right click 
      e.Handled = true; 
     } 

     private static void listBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
     { 
      SetIsDragClickStarted(sender as DependencyObject, true); 
     } 

     private static void listBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
     { 
      SetIsDragClickStarted(sender as DependencyObject, false); 
     } 

     public static DependencyObject GetParent(DependencyObject obj) 
     { 
      if (obj == null) 
       return null; 

      var ce = obj as ContentElement; 
      if (ce == null) return VisualTreeHelper.GetParent(obj); 

      var parent = ContentOperations.GetParent(ce); 
      if (parent != null) 
       return parent; 

      var fce = ce as FrameworkContentElement; 
      return fce != null ? fce.Parent : null; 
     } 

     #endregion IsDragSelectionEnabledProperty 

     #region IsDragSelectingProperty 

     public static bool GetIsDragSelecting(DependencyObject obj) 
     { 
      return (bool) obj.GetValue(IsDragSelectingProperty); 
     } 

     public static void SetIsDragSelecting(DependencyObject obj, bool value) 
     { 
      obj.SetValue(IsDragSelectingProperty, value); 
     } 

     public static readonly DependencyProperty IsDragSelectingProperty = 
      DependencyProperty.RegisterAttached("IsDragSelecting", typeof (bool), typeof (DragSelectionHelper), 
       new UIPropertyMetadata(false, IsDragSelectingPropertyChanged)); 

     private static void IsDragSelectingPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
     { 
      var listBoxItem = o as ListBoxItem; 

      if (listBoxItem == null) 
       return; 

      if (!GetIsDragClickStarted(listBoxItem)) return; 

      if (GetIsDragSelecting(listBoxItem)) 
      { 
       listBoxItem.IsSelected = true; 
      } 
     } 

     #endregion IsDragSelectingProperty 

     #region IsDragClickStartedProperty 

     public static bool GetIsDragClickStarted(DependencyObject obj) 
     { 
      return (bool) obj.GetValue(IsDragClickStartedProperty); 
     } 

     public static void SetIsDragClickStarted(DependencyObject obj, bool value) 
     { 
      obj.SetValue(IsDragClickStartedProperty, value); 
     } 

     public static readonly DependencyProperty IsDragClickStartedProperty = 
      DependencyProperty.RegisterAttached("IsDragClickStarted", typeof (bool), typeof (DragSelectionHelper), 
       new FrameworkPropertyMetadata(false, IsDragClickStartedPropertyChanged) {Inherits = true}); 

     private static void IsDragClickStartedPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
     { 
      var listBox = obj as ListBox; 

      if (listBox == null) 
       return; 

      if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) 
       return; 

      var hitTestResult = VisualTreeHelper.HitTest(listBox, Mouse.GetPosition(listBox)); 
      if (hitTestResult == null) 
       return; 

      var element = hitTestResult.VisualHit; 
      while (element != null) 
      { 
       var scrollBar = element as ScrollBar; 
       if (scrollBar != null) 
       { 
        return; 
       } 
       element = VisualTreeHelper.GetParent(element); 
      } 

      if (GetIsDragClickStarted(listBox)) 
       listBox.SelectedItems.Clear(); 
     } 

     #endregion IsDragClickInitiatedProperty 
    } 
} 

데모 : 나는 그것을 해결 Demo

+0

감사합니다. 오류를 생성 한 변경된 네임 스페이스를 제외하고는 거의 복사하여 붙여 넣기였습니다 (시작 부분에 작은 부분 인 "public partial class Window1 : Window"). – TripleAntigen