Make the WPF window draggable, no matter which item is clicked

My question is 2 times, and I hope that there are simpler solutions provided by WPF , and not standard WinForms solutions (which Christophe Geers provided before I clarified this).

Firstly, is there a way to make Window draggable without capturing and handling mouse click + drag events? I mean, the window is being dragged in the title bar, but if I set the window to not have it and still want to drag it, is there a way to just redirect the events anyway to what the title bar drags

Secondly, is there a way to apply an event handler to all window elements? As with the case, make the window draggable regardless of which element the user clicks + drags. Obviously, without adding a handler manually, for each individual element. Just do it somewhere somewhere?

+89
user-interface c # wpf drag-and-drop
Sep 14 '11 at 2:09 p.m.
source share
9 answers

Of course, apply the following MouseDown event to your Window

 private void Window_MouseDown(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) this.DragMove(); } 

This will allow users to drag the window when they click / drag any control, EXCEPTION for controls that contain the MouseDown event ( e.Handled = true )

You can use PreviewMouseDown instead of MouseDown , but the drag event eats the Click event, so your window stops responding to mouse events. If you REALLY want to click and drag a form from any control, perhaps you can use PreviewMouseDown , start a timer to start the drag operation, and cancel the operation if the MouseUp event fires for X milliseconds.

+233
Sep 14 '11 at 15:08
source share

if you need to drag and drop the wpf form no matter where it was clicked, the simple job is to use the delegate to run the DragMove () method either in the onload windows event or in the grid load event

 private void Grid_Loaded(object sender, RoutedEventArgs { this.MouseDown += delegate{DragMove();}; } 
+7
Nov 30 '13 at 13:07 on
source share

Sometimes we do not have access to Window , for example. if we use DevExpress , all that is available is a UIElement .

Step 1: Add an Attached Property

Decision:

  • Connect to MouseMove events;
  • Search for the visual tree until we find the first parent of Window ;
  • Call .DragMove() on our newly opened Window .

the code:

 using System.Windows; using System.Windows.Input; using System.Windows.Media; namespace DXApplication1.AttachedProperty { public class EnableDragHelper { public static readonly DependencyProperty EnableDragProperty = DependencyProperty.RegisterAttached( "EnableDrag", typeof (bool), typeof (EnableDragHelper), new PropertyMetadata(default(bool), OnLoaded)); private static void OnLoaded(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) { var uiElement = dependencyObject as UIElement; if (uiElement == null || (dependencyPropertyChangedEventArgs.NewValue is bool) == false) { return; } if ((bool)dependencyPropertyChangedEventArgs.NewValue == true) { uiElement.MouseMove += UIElementOnMouseMove; } else { uiElement.MouseMove -= UIElementOnMouseMove; } } private static void UIElementOnMouseMove(object sender, MouseEventArgs mouseEventArgs) { var uiElement = sender as UIElement; if (uiElement != null) { if (mouseEventArgs.LeftButton == MouseButtonState.Pressed) { DependencyObject parent = uiElement; int avoidInfiniteLoop = 0; // Search up the visual tree to find the first parent window. while ((parent is Window) == false) { parent = VisualTreeHelper.GetParent(parent); avoidInfiniteLoop++; if (avoidInfiniteLoop == 1000) { // Something is wrong - we could not find the parent window. return; } } var window = parent as Window; window.DragMove(); } } } public static void SetEnableDrag(DependencyObject element, bool value) { element.SetValue(EnableDragProperty, value); } public static bool GetEnableDrag(DependencyObject element) { return (bool)element.GetValue(EnableDragProperty); } } } 

Step 2: add an attached property to any element so that it drags the window

The user can drag the whole window by clicking on a specific element if we add this attached property:

 <Border local:EnableDragHelper.EnableDrag="True"> <TextBlock Text="Click me to drag this entire window"/> </Border> 



Appendix A: Additional Advanced Example

In this example from DevExpress, we replace the dock window title bar with our own gray rectangle, and then make sure that if the user clicks and drags the specified gray rectangle, the window will usually be dragged:

 <dx:DXWindow x:Class="DXApplication1.MainWindow" Title="MainWindow" Height="464" Width="765" xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking" xmlns:local="clr-namespace:DXApplication1.AttachedProperty" xmlns:dxdove="http://schemas.devexpress.com/winfx/2008/xaml/docking/visualelements" xmlns:themeKeys="http://schemas.devexpress.com/winfx/2008/xaml/docking/themekeys"> <dxdo:DockLayoutManager FloatingMode="Desktop"> <dxdo:DockLayoutManager.FloatGroups> <dxdo:FloatGroup FloatLocation="0, 0" FloatSize="179,204" MaxHeight="300" MaxWidth="400" local:TopmostFloatingGroupHelper.IsTopmostFloatingGroup="True" > <dxdo:LayoutPanel ShowBorder="True" ShowMaximizeButton="False" ShowCaption="False" ShowCaptionImage="True" ShowControlBox="True" ShowExpandButton="True" ShowInDocumentSelector="True" Caption="TradePad General" AllowDock="False" AllowHide="False" AllowDrag="True" AllowClose="False" > <Grid Margin="0"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Border Grid.Row="0" MinHeight="15" Background="#FF515151" Margin="0 0 0 0" local:EnableDragHelper.EnableDrag="True"> <TextBlock Margin="4" Text="General" FontWeight="Bold"/> </Border> <TextBlock Margin="5" Grid.Row="1" Text="Hello, world!" /> </Grid> </dxdo:LayoutPanel> </dxdo:FloatGroup> </dxdo:DockLayoutManager.FloatGroups> </dxdo:DockLayoutManager> </dx:DXWindow> 



Disclaimer: I am not an affiliate of DevExpress . This method will work with any user element, including standard WPF or Telerik (another excellent WPF library provider).

+4
Mar 11 '16 at 16:34
source share
 private void Window_MouseDown(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) this.DragMove(); } 

Throws an exception in some cases (that is, if you also have a clickable image in the window that, when clicked, opens a message window. When you exit the message window, you will get an error)

 private void Window_MouseDown(object sender, MouseButtonEventArgs e) { if (Mouse.LeftButton == MouseButtonState.Pressed) this.DragMove(); } 

So, you are sure that the left button is pressed at this moment.

+3
Feb 05 '15 at 21:01
source share

You can drag a form by clicking anywhere on the form, not just the title bar. This is useful if you have a borderless form.

This CodeProject article demonstrates one possible solution to implement this:

http://www.codeproject.com/KB/cs/DraggableForm.aspx

Basically, a descendant of the form type is created in which the mouse, up and move operations are processed.

  • Mouse down: remember position
  • Mouse move: save new location
  • Mouse up: position shape to a new place

And here a similar solution is explained in the video tutorial:

http://www.youtube.com/watch?v=tJlY9aX73Vs

I do not allow dragging and dropping the form when the user clicks on the control in the specified form. Epexct users get different results when they click on different controls. When my form suddenly starts to move, because I clicked on the list, button, shortcut ... etc. it will be confused.

+2
Sep 14 '11 at 2:35 a.m.
source share

This is all you need!

 private void UiElement_MouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { if (this.WindowState == WindowState.Maximized) // In maximum window state case, window will return normal state and continue moving follow cursor { this.WindowState = WindowState.Normal; Application.Current.MainWindow.Top = 3;// 3 or any where you want to set window location affter return from maximum state } this.DragMove(); } } 
+1
Jan 17 '18 at 15:05
source share

The most useful method for both WPF and Windows, an example of WPF:

  [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam); public static void StartDrag(Window window) { WindowInteropHelper helper = new WindowInteropHelper(window); SendMessage(helper.Handle, 161, 2, 0); } 
0
Sep 19 '14 at 18:04
source share
 <Window ... WindowStyle="None" MouseLeftButtonDown="WindowMouseLeftButtonDown"/> <x:Code> <![CDATA[ private void WindowMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { DragMove(); } ]]> </x:Code> 

source

0
May 11 '17 at a.m.
source share

As @ fjch1997 already mentioned , this is convenient for implementing behavior. Here it is, the basic logic is the same as @ loi.efy's answer :

 public class DragMoveBehavior : Behavior<Window> { protected override void OnAttached() { AssociatedObject.MouseMove += AssociatedObject_MouseMove; } protected override void OnDetaching() { AssociatedObject.MouseMove -= AssociatedObject_MouseMove; } private void AssociatedObject_MouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && sender is Window window) { // In maximum window state case, window will return normal state and // continue moving follow cursor if (window.WindowState == WindowState.Maximized) { window.WindowState = WindowState.Normal; // 3 or any where you want to set window location after // return from maximum state Application.Current.MainWindow.Top = 3; } window.DragMove(); } } } 

Using:

 <Window ... xmlns:h="clr-namespace:A.Namespace.Of.DragMoveBehavior" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"> <i:Interaction.Behaviors> <h:DragMoveBehavior /> </i:Interaction.Behaviors> ... </Window> 
0
Dec 20 '18 at 11:43
source share



All Articles