English 中文(简体)
缩略语
原标题:wpf listview drag select multiple items
  • 时间:2010-05-19 21:30:18
  •  标签:
  • .net
  • wpf

有理由怀疑任何人对如何做到这一点是否有任何想法。 我想让用户选择多个项目,点击和拖拉(不要点击)。 用户在项目1上点击,然后拖到项目10;项目1至10应选定为点击项目1,然后转而点击项目10。

让我知道感谢!

最佳回答

我在此提出解决办法,我设立了一个处理PreviewLeftMouseButtonDown和MouseLeftButton的助手班。 在清单意见中,以及在清单中采用一种小的风格,即当变数反映的是助手类别时,它可以决定它是否选择该项目(根据左纽州的压力或没有)。 任何方面,在此,整个项目:

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"
                 当地: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
    }
}

如你所看到,你们都需要做的是,在你身上添加大体,并确定:

当地:DragSelectionHelper.IsDragSelectionEnabled=“true”

该财产附在《清单》中,而且该财产涉及所有事项。

感谢!

问题回答

根据Carlos的答复,我修改了他的一些法典,现在你可以利用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: Demo

并请注意,如果用户在停用之前将SHIFT 钥匙搁置起来,可在<代码>上填满>。





相关问题
Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How do I compare two decimals to 10 decimal places?

I m using decimal type (.net), and I want to see if two numbers are equal. But I only want to be accurate to 10 decimal places. For example take these three numbers. I want them all to be equal. 0....

Exception practices when creating a SynchronizationContext?

I m creating an STA version of the SynchronizationContext for use in Windows Workflow 4.0. I m wondering what to do about exceptions when Post-ing callbacks. The SynchronizationContext can be used ...

Show running instance in single instance application

I am building an application with C#. I managed to turn this into a single instance application by checking if the same process is already running. Process[] pname = Process.GetProcessesByName("...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签