5,660,782 members and growing! (17,219 online)
Email Password   helpLost your password?
Desktop Development » List Controls » ListView controls     Beginner License: The GNU Lesser General Public License

Enable MultiSelect in WPF ListView

By Leung Yat Chun

Make your ListView support Item Selection by Dragging,
C# (C#, C# 3.0), Windows (Windows, WinXP, Win2003, Vista), .NET (.NET 3.5, .NET, .NET 3.0), Visual Studio (Visual Studio, VS2008), WPF, Design

Posted: 1 May 2008
Updated: 13 May 2008
Views: 8,205
Bookmarked: 7 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
2 votes for this Article.
Popularity: 1.00 Rating: 3.33 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
1 vote, 50.0%
3
1 vote, 50.0%
4
0 votes, 0.0%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

This Article demos how to create a component that enable multiselect support for your Listview.

Background

I was developing a filelist, I didn't take much attention to selection mode, as I thought setting ListView.SelectionMode to Multiple/Extended will make the items in ListView by click and dragging. (thats my .Net 1.1 book told me).

Then when it's almost completed, I have time to do more test, unable to select more that one item is very annoying, so I set the selection mode to Multiple.

<ListView SelectionMode="Multiple"  .../>  


Recompile, It seems not working, no matter if I compile it a couple times, start dragging from empty space, change the SelectionMode to Extended, it simply not working.

I end up figured out although it allow me to select multiple items using Control and Shift, I cannot use mouse drag to select. I am not sure about other people, but this is really a big surprise for me.

It is wired that even though this is supposed a big common problem, I cannot Google a helpful / completed solution, allow multiple select is very important to my filelist, so I develop this component with my limited WPF knowledge.

My Design process

When I start, I tried to find the position of each ListViewItem and compare with select region, did some research but no luck :

  • There seems no common place to store which ListViewItem located in where, unless you developed your own Panel.
  • It seems possible to override OnMouseMove of TreeViewItem, but this will limit your ListView can use in StackPanel template only, as it require your mouse above the TreeViewItem. (See MultiSelectListView in demo project)
  • Arrange method expose size only, ArrangeCore method can expose a rect, but it is sealed.

After some Googling, I found a method named VisualTreeHelper.HitTest, which takes

  • a control,
  • a filter function, (retrive selected item via this func)
  • a result callback and
  • a rect.

and return child items in the specified rect.

It does what I wanted, but the HitTest method can return only the visible item, so if I start select, then scroll down, it will search only the items on screen, not the hidden items. This is then fixed by HitTest twice, first unselect all visible items, second select selected visible items.

//Unselect all visible selected items  no matter if it's current selected or not.
VisualTreeHelper.HitTest(lvSender, UnselectHitTestFilterFunc,
  new HitTestResultCallback(SelectResultCallback),
  new GeometryHitTestParameters(new RectangleGeometry(unselectRect))); 
   
//Select all visible items in select region.
VisualTreeHelper.HitTest(lvSender, SelectHitTestFilterFunc,
   new HitTestResultCallback(SelectResultCallback),
   new GeometryHitTestParameters(new RectangleGeometry(selectRect)));

The last problem is to draw the preview rectangle, which is visible when selecting, as my knowledge is limited, all I can do is to draw it in background, please post if you have a better solution. (As you see, the preview rectangle cannot deal with Scrolling, I havent figured out how to obtain scrolling information yet)

lvSender.Background = new DrawingBrush(
   DrawRectangle(selectRect, lvSender.ActualWidth, lvSender.ActualHeight));

Using the code

I have created a component for this operation, you can include the code in your project and set a Attached property to enable MultiSelect, you may have to set the ItemPanel Template so there is space for start dragging.
<ListView cont:ListViewSelectionHelper.MultiSelect="True"                   
             cont:ListViewSelectionHelper.PreviewDrag="True">
       <ListView.ItemsPanel>
           <ItemsPanelTemplate>
               <StackPanel Margin="0,0,20,0" IsItemsHost="True" />
           </ItemsPanelTemplate>
       </ListView.ItemsPanel>
       <ListView.Items>
           <TextBlock>Test1</TextBlock>
           <TextBlock>Test2</TextBlock>
           <TextBlock>Test3</TextBlock>
           <TextBlock>Test4</TextBlock>
           <TextBlock>Test5</TextBlock>
       </ListView.Items>
 </ListView>
        

Setting the MultiSelect will attach 4 events to your ListView :
1. PreviewMouseDown, to clear selections.
2. MouseDown, to enable IsDragging attached property.
3. MouseUp, to disable IsDragging attached property.
4. MouseMove, if IsDragging, select the items.

How it looks when MultiSelect on my filelist

2.jpg

History

05-02-08 Initial version (hopefully not the last version)
05-13-08 Version 2, Fixed 3 Bugs :
- Cannot drag if Scrollbar not visible.
- Strange selection effect after drag.
- Shift+Select not work as intended.


License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License

About the Author

Leung Yat Chun



Location: Hong Kong Hong Kong

Other popular List Controls articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
  (Refresh) 
-- There are no messages in this forum --

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 13 May 2008
Editor:
Copyright 2008 by Leung Yat Chun
Everything else Copyright © CodeProject, 1999-2008
Web16 | Advertise on the Code Project