Click here to Skip to main content
15,860,861 members
Articles / Programming Languages / C#

Rubberband Behavior for WPF ListBox

Rate me:
Please Sign up or sign in to vote.
5.00/5 (16 votes)
16 Jun 2012CPOL3 min read 49.7K   2.6K   27   11
The article describes how to implement Rubberband behavior for WPF Listbox. Also it describes how to add the behavior using Expression Blend.

Introduction 

The article describes how to implement Rubberband behavior for WPF Listbox. Also it describes how to add this behavior using Expression Blend.

Image 1

Background

1. Multiple Selection for WPF Listbox. 

http://msdn.microsoft.com/en-us/library/system.windows.controls.listbox.selectionmode

2. Add custom behaviors through Expression Blend 

http://msdn.microsoft.com/en-us/library/ee341397(v=expression.40).aspx 

Project Structure 

The sample project structure goes like this,

Project Structure 

Rubberband project contains the corresponding behavior. RubberBand class holds the UI logic to render the rubberband. RubberBandSelection is the demo project which contains the ListBox with Multiple Selection. 

Using the code  

Let me split the article in 3 sections. First creating a custom behavior in WPF 4.0. And rendering a rubberband adorner in Window. Finally how to add the behavior in Expression blend assets for reuse.

Creating Custom Behavior 

Behaviors are used to encapsulate simple pieces of functionality into a single component for easy reuse. The Behaviors can be associated to any WPF object to give an additional behavior to the control. Example of a behaviors are drag&drop, input validation, pan and zoom, re-position of elements, etc... The list of possible behaviors is very long.

Custom behaviors can be created by inheriting from System.Windows.Interactivity.Behavior class. 

[DescriptionAttribute("Enable Rubberband selection for a WPF listbox object.")]
public class RubberBandBehavior : Behavior<ListBox>
{
        protected override void OnAttached()
        {
            AssociatedObject.Loaded += new System.Windows.RoutedEventHandler(AssociatedObject_Loaded);
            base.OnAttached();
        }
        void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            RubberBandAdorner band = new RubberBandAdorner(AssociatedObject);
            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(AssociatedObject);
            adornerLayer.Add(band);
        }
        protected override void OnDetaching()
        {
            AssociatedObject.Loaded -= new System.Windows.RoutedEventHandler(AssociatedObject_Loaded);
            base.OnDetaching();
        }
} 

Creating Rubberband Adorner 

Create a Rubberband adorner by inheriting from Adorner class. Adorners are a special type of FrameworkElement, used to provide visual cues to a user. Among other uses, Adorners can be used to add functional handles to elements or provide state information about a control.

Adorners are rendered in an AdornerLayer, which is a rendering surface that is always on top of the adorned element or a collection of adorned elements. Rendering of an adorner is independent from rendering of the UIElement that the adorner is bound to. An adorner is typically positioned relative to the element to which it is bound, using the standard 2-D coordinate origin located at the upper-left of the adorned element. 

public RubberBandAdorner(UIElement adornedElement)
:base(adornedElement)
{
}  

To bind an adorner to a particular UIElement, follow these steps:

1. Call the static method GetAdornerLayer to get an AdornerLayer object for the UIElement to be adorned. GetAdornerLayer walks up the visual tree, starting at the specified UIElement, and returns the first adorner layer it finds. (If no adorner layers are found, the method returns null.)

2. Call the Add method to bind the adorner to the target UIElement. 

RubberBandAdorner band = new RubberBandAdorner(AssociatedObject);
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(AssociatedObject);
adornerLayer.Add(band); 

Subscribe the Mouse Down and Mouse Move events and get the start point and current point. Use the OnRender override to render the visual. 

protected override void OnRender(DrawingContext drawingContext)
{
     Rect rect = new Rect(startpoint, currentpoint);
     drawingContext.DrawGeometry(brush, new Pen(SystemColors.HighlightBrush, 1), new RectangleGeometry(rect));
     base.OnRender(drawingContext);
} 

The base idea is while moving the mouse, calculate the current position of mouse and draw the Rubberband adorner over the ListBox. OnRender override method can be invoked manually by using InvalidateVisual(). On every mouse move determine the listbox items within the rubberband rect and make it selected. 

foreach (var obj in _selector.Items)
{
   ListBoxItem item = _selector.ItemContainerGenerator.ContainerFromItem(obj) as ListBoxItem;
   if (item != null)
   {
       Point point = item.TransformToAncestor(AdornedElement).Transform(new Point(0, 0));
       Rect bandrect = new Rect(startpoint, currentpoint);
       Rect elementrect = new Rect(point.X, point.Y, item.ActualWidth, item.ActualHeight);
       if (bandrect.IntersectsWith(elementrect))
       {
             item.IsSelected = true;
       }
       else
       {
             item.IsSelected = false;
       }
   }
} 

Add custom behavior in Expression Blend 

Copy the RubberBand.dll in the following location, 

C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries 

Image 3

1. Open the Expression Blend.   

2. Create a new WPF project. 

3. Open the Assets -> Behaviors panel. You will find the RubberBandBehavior in the list.

Image 4

4. Drag and drop the behavior into the Listbox object in the designer. Make sure you set the Selection mode of Listbox to Multiple or Extended.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
Jawahar working as a Senior Development Engineer in Aditi Technologies,Bangalore, India. Specialist in all XAML frameworks. Very passionate on UX Design and Development. Skilled in Expression Blend, Design, WPF, Silverlight, Windows Phone 7/8, Windows 8. Good knowledge in Entity Framework, SQLite and SQL Server also. Also had good experience with PRISM, MVVM, Caliiburn Micro and other design patterns.

He developed few products for Syncfusion Inc. Also working on some freelancing projects. Worked as a lead developer of Metro Studio from Syncfusion Inc.

An active freelancer. http://xamlfactory.elance.com

http://about.me/jawahars

http://wpfplayground.com/

Comments and Discussions

 
QuestionExtension for more complicated GUIs. Pin
Member 101146089-Aug-13 10:39
Member 101146089-Aug-13 10:39 
Questionwhat is Rubberband Behavior Pin
Tridip Bhattacharjee10-Jul-13 5:13
professionalTridip Bhattacharjee10-Jul-13 5:13 
QuestionA question for Rubberband behavior Pin
dennis_dana25-Jun-13 0:03
dennis_dana25-Jun-13 0:03 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey26-Apr-13 18:37
professionalManoj Kumar Choubey26-Apr-13 18:37 
General5 from me, too Pin
Caipus22-Feb-13 1:21
Caipus22-Feb-13 1:21 
QuestionNice solution Pin
Caipus21-Feb-13 19:26
Caipus21-Feb-13 19:26 
GeneralMy vote of 5 Pin
Member 959770618-Nov-12 11:08
Member 959770618-Nov-12 11:08 
QuestionIs this like XOR Pin
Member 959770618-Nov-12 11:08
Member 959770618-Nov-12 11:08 
GeneralMy vote of 5 Pin
tal_segal18-Jun-12 19:32
tal_segal18-Jun-12 19:32 
GeneralMy vote of 1 Pin
Klaus Luedenscheidt16-Jun-12 18:18
Klaus Luedenscheidt16-Jun-12 18:18 
GeneralRe: My vote of 1 Pin
Richard Deeming21-Jun-12 7:49
mveRichard Deeming21-Jun-12 7:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.