Click here to Skip to main content
15,867,785 members
Articles / Desktop Programming / WPF
Tip/Trick

Draggable Popup

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
5 Jan 2017CPOL1 min read 15.2K   519   6   1
This is a simple popup that includes drag capability. The code should be helpful to anyone looking to create a control drag capability.

Introduction

I was asked to put up a dialog while the application was busy that could be dragged, allowing the user to move it out of the way so that he could see what was underneath.

Background

I had tried several things I found online but did not really like any of them, and some actually had issues.

The Code

The DraggablePopup derives from the Popup class. The overridden OnInitialized method checks that the Popup has content. This is because the Popup cannot be clicked on. The content, or Child, should contain a FrameworkElement that encompases any part of the Popup that the designer wants to allow the user to click and drag with. The OnInitialized method, after checking that there is content, then attaches handlers for the MouseLeftButtonDown, MouseLeftButtonUp and MouseMove events:

C#
public class DraggablePopup : Popup
{
 Point _initialMousePosition;
 bool _isDragging ;

 protected override void OnInitialized(EventArgs e)
 {
  var contents = Child as FrameworkElement;
  Debug.Assert(contents != null, "DraggablePopup either has no content if content that " +
   "does not derive from FrameworkElement. Must be fixed for dragging to work.");
  contents.MouseLeftButtonDown += Child_MouseLeftButtonDown;
  contents.MouseLeftButtonUp += Child_MouseLeftButtonUp;
  contents.MouseMove += Child_MouseMove;
 }

 private void Child_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 {
  var element = sender as FrameworkElement;
  _initialMousePosition = e.GetPosition(null);
  element.CaptureMouse();
  _isDragging = true;
  e.Handled = true;
 }

 private void Child_MouseMove(object sender, MouseEventArgs e)
 {
  if (_isDragging)
  {
   var currentPoint = e.GetPosition(null);
   HorizontalOffset = HorizontalOffset + (currentPoint.X - _initialMousePosition.X);
   VerticalOffset = VerticalOffset + (currentPoint.Y - _initialMousePosition.Y);
  }
 }

 private void Child_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
 {
  if (_isDragging)
  {
   var element = sender as FrameworkElement;
   element.ReleaseMouseCapture();
   _isDragging = false;
   e.Handled = true;
  }
 }
}

There are two private fields: one to indicate that a drag operation is in progress, and the other to contain the initial location that dragging started. The MouseLeftButtonDown and MouseLeftButtonUp event handlers basically start and end the process by setting the bool IsDragging field, and the MouseLeftButtonDown also sets the initial location of the click. Then the MouseMove adjusts the location of the Popup.

Using the Code

I have used a Border as the content in the sample. There is a Button within the Border that allows the Popup to be closed, but is not shown in the code below. I have set the Placement as Center to the containing Window. From my experience, the way Placement works is different on a Window than other controls. In other controls, to get the Popup centered, I had to use the HorzontalOffset and VerticalOffset since the top left corner is what is centered.

XML
<local:DraggablePopup Width="300"
                      Height="200"
                      IsOpen="{Binding ElementName=WindowToggleButton,
                                       Path=IsChecked}"
                      Placement="Center"
                      PlacementTarget="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
                     >
 <Border Background="LightGray"
         BorderBrush="Black"
         BorderThickness="1" >
  </Border>
</local:DraggablePopup>

Image 1

Image 2

Image 3

History

  • 2016/12/23: Initial version

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) Clifford Nelson Consulting
United States United States
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last eight years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with BioNano Genomics in San Diego, CA redesigning their UI for their camera system. he can be reached at qck1@hotmail.com.

Comments and Discussions

 
QuestionDragging PopUp is correct Pin
Member 161103748-Oct-23 19:34
Member 161103748-Oct-23 19:34 

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.